Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 26.05.2016
Сообщений: 9
1

Смысл использования полиморфизма

26.05.2016, 14:03. Показов 1147. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
 
using namespace std;
 
class A{
 
public:
    virtual void speak() {}
 
};
 
class B: public A{
public:
    void speak() {
        cout << "class a" << endl;
    }
 
};
 
class C: public A{
public:
    void speak() {
        cout << "class b" << endl;
    }
 
};
 
int main() {
 
    B lo;
    C na;
 
    A *en1 = &lo;
    A *en2 = &na;
 
    en1->speak();
    en2->speak();
 
    return 0;
}
Я не могу никак понять, для чего он нужен. Это - пример полиморфизма через виртуальные функции.
Мы создаем объекты lo и na, после создаем указатели на класса A и присваем им адреса наших предыдущих объектов, в результате, благодаря нашему виртуальному методу speak(), уникальные реализации классов-наследников доступны через базовый класс.
Это все замечательно, но почему? Каждый раз, чтобы это сделать, нужно создавать en1,en2 , хотя т.к. уже есть наследование, то методы доступны и через lo и na. Да, мы реализовали доступ через базовый класс. Но зачем?
Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.05.2016, 14:03
Ответы с готовыми решениями:

В чем смысл полиморфизма
Объясните, пожалуйста, смысл полиморфизма. Не могу никак вникнуть. Где и как он используется? И...

Пример использования генератора случайных чисел для демонстрации динамического полиморфизма
Пример использования генератора случайных чисел для демонстрации динамического полиморфизма.Я в...

В чём смысл использования указателей на функции
Собсно,я не могу понять,в чём смысл использования указателей на функции,ведь можно вызывать...

Правильное понимание и обоснование использования полиморфизма
Всем привет! Помогите понять полиморфизм правильно. Так как примеров в Интернете много и все они...

5
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,714
26.05.2016, 14:33 2
Лучший ответ Сообщение было отмечено Dobbyman как решение

Решение

Цитата Сообщение от Dobbyman Посмотреть сообщение
Я не могу никак понять, для чего он нужен
Обратите внимание
Цитата Сообщение от Dobbyman Посмотреть сообщение
C++
1
2
en1->speak(); 
en2->speak();
Оба указателя - это указатели на базовый класс A.
Однако, в первом случае вызывается метод класса B,
а во втором - метод класса A.

Как раз в этом и есть смысл.
Мы заранее не знаем, как метод будет реализован в производном классе,
Но можем написать код, который вызовет этот метод.
1
Заблокирован
26.05.2016, 14:36 3
Помогает расширяемости. Программа, которая использует указатель на A и вызывает speak() не нуждается в перекомпиляции существующего кода, и сорцы существующих классов не нуждаются в изменении для добавления нового функционала в метод speak. Таким образом снижаются риски при программировании. Ты расширяешь функционал приложения, не меняя существующий код. Если грубо и вкратце.
Конечно, если ты свои классы, как путный программист, отправишь в отдельные модули, а не все в одном, как сейчас.
1
693 / 303 / 99
Регистрация: 04.07.2014
Сообщений: 846
26.05.2016, 15:26 4
Dobbyman, Плохой пример выбрал.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
#include <vector>
 
class Animal {
public:
  virtual ~Animal() = default;
  virtual std::string talk() = 0;
};
 
class Cat : public Animal {
public:
  virtual ~Cat() = default;
  virtual std::string talk() override
  {
    return "Meow!";
  };
};
 
class Dog : public Animal {
public:
  virtual ~Dog() = default;
  virtual std::string talk() override
  {
    return "Woof!";
  };
};
 
int main()
{
  std::vector<Animal *> animals;
  animals.push_back(new Cat());
  animals.push_back(new Dog());
  animals.push_back(new Cat());
 
  for (size_t i = 0; i < animals.size(); ++i) {
    std::cout << i << ": " << animals[i]->talk() << std::endl;
  }
 
  for (size_t i = 0; i < animals.size(); ++i) {
    delete animals[i];
  }
 
  return 0;
}
Результат:
Код
0: Meow!
1: Woof!
2: Meow!
1
Эксперт С++
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
26.05.2016, 17:17 5
Цитата Сообщение от Dobbyman Посмотреть сообщение
Это все замечательно, но почему? Каждый раз, чтобы это сделать, нужно создавать en1,en2 , хотя т.к. уже есть наследование, то методы доступны и через lo и na. Да, мы реализовали доступ через базовый класс. Но зачем?
Ну, чтобы это понять, нужно получше разобраться что такое открытое наследование. А это некоторая специализация базового класса, т.е. описание некоторого подмножества множества объектов базового класса.
Ну, к примеру, базовый класс у нас Станок. И у множества объектов-станков есть подмножество объектов - сверлильных станков. Для описания этого подмножества объявляем класс-наследник Сверлильный_станок. Базовый класс можно специализировать в наследнике просто добавляя новые члены (данные и функции), а можно специализировать поведение базовых функций-членов, это как раз и делается через механизм виртуальных функций.
Ну, допустим, вы отдаете всем объектам-станкам в цеху команду Обработать_деталь. С одной стороны, это базовая функция-член класса Станок, так как все станки должны обрабатывать детали. С другой - каждый станок обрабатывает деталь в соответствии со своей специализацией, - сверлильный - сверлит, токарный точит, и т.д.
Технически для этого нужно создать коллекцию указателей на базовый класс Станок, и поместить туда адреса всех объектов-станков. Тогда, чтобы каждый станок начал обрабатывать деталь, нужно всем станкам дать команду Обработать_деталь, и каждый выполнит ее в соответствии со своей специализацией.
1
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 629
Регистрация: 04.12.2011
Сообщений: 13,999
Записей в блоге: 16
26.05.2016, 19:42 6
Цитата Сообщение от Dobbyman Посмотреть сообщение
хотя т.к. уже есть наследование, то методы доступны и через lo и na.
Если бы и не было наследования они были бы доступны через экземпляры классов A и B, например через lo и na. Дело не в том что они недоступны, а в том как они доступны. Если Вы хотите создать коллекцию родственных сущностей вроде экземпляров A и B можно бы создать класс С в котором есть указатели на A и B и метод который вызывает метод speak того объекта, указатель на который не равен nullPtr. Тогда имея контейнер объектов С можно пройти по нему вызвав метод speak(). Это будет работать если A и B не родственники и единственное что их объеденияет это то, что они умеют void speak(); (это тоже не обязательно с формальной точки зрения).
При использовании полиморфизма итерация с вызовом speak() идёт по контейнеру указателей на базовый класс инициализированных адресами объектов A и B (которые родственники). Это легче.
1
26.05.2016, 19:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.05.2016, 19:42
Помогаю со студенческими работами здесь

Смысл использования using в коде
Часто встречаю использование using внутри кода, например. using (TextReader textReader = new...

Смысл использования интерфейсов
Добрый вечер. Дошел в самоучителе до главы про интерфейсы и в целом мне понятен синтаксис, но я...

Смысл использования this в конструкторе
Какой смысл использовать this в конструкторе(Как написано ниже)? Я понимаю что this нужен для того,...

Смысл использования отдельной переменной?
Объясните, пожалуйста, в чем смысл занесения переменной &quot;e&quot; в коде ниже внутрь новой переменной...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru