Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
4 / 4 / 3
Регистрация: 13.07.2014
Сообщений: 129
1

В чем смысл полиморфизма

19.07.2015, 22:57. Показов 2209. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Объясните, пожалуйста, смысл полиморфизма. Не могу никак вникнуть. Где и как он используется? И примерчик, пожалуйста
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.07.2015, 22:57
Ответы с готовыми решениями:

Смысл использования полиморфизма
#include <iostream> using namespace std; class A{ public: virtual void speak() {} };

В чем смысл указателей?
Дорогие друзья, не могу понять смысл указателей в С++? Для чего они нужны? Если не трудно на...

В чем смысл виртуальных функций?
Читаю книгу Джесс Либерти 'С++ за 21 день', не смотря на глупое название, книга очень грамотная и...

В чем смысл перегрузки функций?
Недавно прошел тему перегрузки и был вот такой код: #include <iostream> using namespace std;...

17
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
19.07.2015, 23:56 2
прочитайте книги, статьи.
0
4 / 4 / 3
Регистрация: 13.07.2014
Сообщений: 129
20.07.2015, 00:00  [ТС] 3
rikimaru2013, читал. Вроде как понял, но вот примера нормального не нашел. По этому так и не понял, зачем полиморфизм нужен
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
20.07.2015, 00:19 4
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
46
47
48
49
50
51
52
53
#include <iostream>
#include <vector>
using namespace std;
class Figure
{
public:
    virtual float getSquare() = 0;
};
 
class Rectangle :
    public Figure
{
public:
    virtual float getSquare()
    {
        return 1; // тут будет крутая формула a * b
    }
};
class Triangle :
    public Figure
{
public:
    virtual float getSquare()
    {
        return 2; // тут будет крутая формула 1.0 / 2.0 * a  * h
    }
};
class Circle :
    public Figure
{
public:
    virtual float getSquare()
    {
        return 3; // тут будет крутая формула 3.14 * r * r
    }
};
 
int main()
{
    vector<Figure*> arr;
    arr.push_back(new Rectangle());
    arr.push_back(new Circle());
    arr.push_back(new Triangle());
    arr.push_back(new Triangle());
    arr.push_back(new Rectangle());
 
 
 
    for(int i = 0; i < arr.size(); i++)
    {
        cout << arr[i]->getSquare() << endl;
    }
}
Добавлено через 2 минуты
В более крутых проектах:
есть понятие в игре юнит - у него виртуальный метод moveTo(); Кто-то идёт пешком, какая-то гарпия летает, кто-то телепортируется по местности, но у всех есть метод moveTo(), который они переопределили для себя. И если появится еще 1 вид передвижения, это не беда, унаследуем, переопределим и будет он ... к примеру, нырять под землю и в нужной точке выныривать.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.07.2015, 09:53 5
Цитата Сообщение от Andrey040601 Посмотреть сообщение
Объясните, пожалуйста, смысл полиморфизма. Не могу никак вникнуть. Где и как он используется? И примерчик, пожалуйста
есть собака, и кошка.
и то, и другое - животные.
собака лает. кошка мяукает.

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
IAnimal
{
    // не забываем про виртуальный диструктор
    virtual ~IAnimal(){}
 
    // все животные умеют издавать звуки
    virtual void sound() = 0;
};
 
struct Dog: IAnimal
{
    virtual void sound() { cout <<"гаф-гаф\n"; }
}
 
struct Cat: IAnimal
{
    virtual void sound() { cout <<"мяу-мяу\n"; }
}
 
// функция не знает с каким именно животным она работает
void sound(IAnimal& animal)
{
 
    // но это не мешает ей воспроизвести звучание любого животного
    // которого ей прислали
 
   // гафкай, или мяукай, в зависимости от того, кто ты там
   animal.sound();
}
рассмотрим класс IAnimal
такие классы любят называть "интерфейсы".
он задает методы управления всеми возможными животными.
в данном случае он сообщает: каким бы ни было животное,
но у него обязательно будет метод sound,
который заставит животное издавать звуки.

и есть кучка наследников: кошки, собаки.
это - разные классы.
у них разное поведение.
в данном случае они по разному звучат.

однако несмотря на их различия,
что бы они начали звучать в обоих случаях используется один и тот же метод.

поэтому, даже не зная точно, кто это:
кошка, или собака, мы можем заставить их звучать.

то есть мы можем выполнять действия над объектами не зная точно,
что именно это за объекты.
главное что бы у них у всех был одинаковый интерфейс.



зачем это нужно?

вот другой пример:

допустим, мы решили создать игрушку.
в игрушке будут бегать разные юниты,
и стрелять друг в друга из разных видов вооружения.

поскольку над проектом будет работать несколько программистов,
то нужно так распределить наши роли,
что бы мы друг другу не мешались.

допустим, вы будете писать код юнитов.
а я - код вооружения.

но как вы сможете писать код юнита, если вооружения ещё никакого нет?
как вы научите своих солдатиков стрелять из оружения, если код оружия ещё не написан?

и вот, мы с вами договариваемя: у любого вида оружия есть интерфейс IWeapon,
у которого есть метод Fire.

что бы юнит сделал выстрел, он должен вызвать этот метод для объект "оружия".
и уже не важно что это за оружие, но если у него есть такой метод,
ваш юнит сможет сделать выстрел.


таким образом, благодаря полиморфизму,
становится возможным солдатикам стрелять из любого вида оружия
(в том числе из такого, чей код ещё даже не написан).

и становится возможным налету (в момент выполнения программы) заменить одно оружие на другое.

солдатик достает пистолет и делает: "пиф-паф!"
а потом достает базуку и делает: "бууумс!"

при этом солдатик не знает как на самом деле устроен объект,
из которого он стреляет.

ему просто пофигу,
он сможет стрелять из любого оружия,
лишь бы у него был спуской крючок: IWeapon::Fire

это делает возможным:
1. командную разработку программного обеспечения, так, что бы никто никому не мешался.
и никого не ждал.

2. гибкость
(можно налету подменять поведение, за счет подмены объектов)

3. расширяемость
(что бы добавить ещё одну пушку - достаточно просто унаследоваться от интерфейса,
и реализовать определенные методы,
и все солдатики априори уже смогут пользоваться новым оружием без изменений в своем коде.).
0
4 / 4 / 3
Регистрация: 13.07.2014
Сообщений: 129
20.07.2015, 10:13  [ТС] 6
Спасибо большое!

Но вот я так и не понял этого:

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
class First
{
public:
    virtual void AnyFunc()
    {
        cout << "First" << endl;
    }
};
 
class Second : public First
{
public:
    virtual void AnyFunc()
    {
        cout << "Second" << endl;
    }
};
 
int main()
{
    First *obj_1 = new Second;
    First *obj_2 = new First;
 
    obj_1->AnyFunc();
    obj_2->AnyFunc();
 
    _getch();
}
В чем смысл
C++
1
 First *obj_1 = new Second;
? Чем оно отличается от
C++
1
 Second *obj_1 = new Second;
?
0
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
20.07.2015, 10:20 7
Смысл полиморфизма в том, что вы вместо базового класса можете использовать наследника. Например (тут рядом моя тема есть) мне нужно выводить информацию из объекта. я передаю ему ссылку (или указатель) на ostream. если пользователь выбирает пункт меню "вывод в файл" для вывода передаётся объект ofstream, если же пользователь выбрал "вывод в консоль", то передаётся cout.
0
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
20.07.2015, 10:23 8
Обратите внимание на то, что в первом случае указателю на БАЗОВЫЙ класс присваивается адрес ПРОИЗВОДНОГО класса.
В этом случае obj_1->AnyFunc(); вызывает виртуальный метод ПРОИЗВОДНОГО класса, т.е. того класса, адрес которого был присвоен.

Соответственно, если присвоен адрес базового класса, то obj_2->AnyFunc(); вызывается метод базового класса.

Second *obj_1 = new Second;obj_1->AnyFunc(); - естественно, вызовется метод производного класса.

А для вызова метода базового класса придется написать
C++
1
obj_1->First::AnyFunc();
0
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
20.07.2015, 10:28 9
вот код для моего примера:
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
#include <iostream>
#include <fstream>
 
using namespace std;
 
void print(ostream* os){
    (*os)<<"hi!";
}
 
int main(){
 
    int c;
 
    cout<<"1 - to console, 2 - to file"<<endl;
 
    cin>>c;
 
    switch (c)
    {
    case 1:
        print(&cout);
        break;
    case 2:
 
        ofstream os;
        os.open("out.txt");
        print(&os);
        os.close();
 
        break;
    }
 
    return 0;
}
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.07.2015, 10:29 10
Цитата Сообщение от Andrey040601 Посмотреть сообщение
В чем смысл
объясняю на примере:

напишите пожалуйста функцию,
которая сможет принимать любые объекты :
First/Second , может быть в будущем ещё наследника добавим.

то есть функция обязана априори принять любого члена иерархии классов.
и дернуть ему функцию AnyFunc.

как вы это сделаете?

-----------------------------------------------------------------------------------
вот у вас есть кошка и собака, а может быть ещё и волк, или лиса.
не важно. у них у всех есть метод "звучать".

напишите функцию, которая умеет принимать объекты любого типа животного,
и заставлять его звучать.

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

я хочу, что бы вы написали только одну.
но эта одна сможет заставить звучать любого животного, которого её пришлют.
1
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
20.07.2015, 10:51 11
VVildVVolf, разъясните подробно, какое отношение имеет Ваш код к теме "Полиморфизм".
0
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
20.07.2015, 10:59 12
функция print принимает указатель на ostream, при этом в функции main эта функция вызывается с передачей аргументов разных типов.

п.с. честно признаюсь, в нюансы именно стримов не вникал досконально, что откуда наследуется и к чему приводится, но использование полиморфизма ВЫГЛЯДИТ примерно так.
0
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
20.07.2015, 11:56 13
Оператор << не является методом класса ostream.
это глобальный перегруженный оператор.
Поэтому в
Цитата Сообщение от VVildVVolf Посмотреть сообщение
(*os)<<"hi!";
никакого полиморфизма нет.
Кроме того, даже если бы и был, то операция разыменования *os приводит к тому,
что этот метод вызывался бы как обычный, а не как виртуальный.
0
82 / 1 / 0
Регистрация: 08.10.2012
Сообщений: 54
20.07.2015, 12:01 14
Цитата Сообщение от zss Посмотреть сообщение
Кроме того, даже если бы и был,
даже если бы и был - это к полиморфизму или к
Цитата Сообщение от zss Посмотреть сообщение
не является методом класса ostream.
?
суть здесь не в перегрузке оператора <<, а в том, что передаются экземпляры разных классов, что влияет на итоговое поведение соответственно. или же в обоих случаях передаются экземпляры одного и того же класса?Оо
0
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
20.07.2015, 12:11 15
VVildVVolf, Вы продемонстрировали не полиморфизм, а родственность производных классов.
Т.е. то, что указателю на базовый класс можно присваивать адрес производного класса без каких-либо преобразований.
0
236 / 196 / 21
Регистрация: 04.06.2014
Сообщений: 1,309
20.07.2015, 12:13 16
Цитата Сообщение от Andrey040601 Посмотреть сообщение
Объясните, пожалуйста, смысл полиморфизма. Не могу никак вникнуть. Где и как он используется? И примерчик, пожалуйста
Ну, на бытовом уровне, смысл полморфизма, когда друзья Вам дают кличку. Вы, уже называетесь в их среде по-другому, но Ваша суть от этого не изменилась-ведь? Вот, в принципе, и всё .
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.07.2015, 12:18 17
Цитата Сообщение от zss Посмотреть сообщение
никакого полиморфизма нет.
есть. статический.

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

но в данном случае он был реализован за счет приведения по иерархии наследования.
это работает, потому что сам по себе std::ostream не более, чем обертка,
которая делегирует задачу своему очень даже полиморфному внутреннему механизму буфера вывода.

http://www.cplusplus.com/reference/ios/ios/rdbuf/

Цитата Сообщение от zss Посмотреть сообщение
операция разыменования *os приводит к тому,
что этот метод вызывался бы как обычный, а не как виртуальный.
ничего подобного.

C++
1
2
3
4
5
IAnimal& reference = getAnimal();
 
reference.virtualMethod(); // <--- для ссылок динамический полиморфизм 
// работает точно так же
// как и для обычных указателей.
Добавлено через 2 минуты
Цитата Сообщение от zss Посмотреть сообщение
Вы продемонстрировали не полиморфизм, а родственность производных классов.
он продемонстрировал два принципиально разных поведения
(вывод в консоль, или вывод в файл),
осуществляемых через единый интерфейс для объектов разных типов.

это и есть красноречивый пример полиморфизма.


"родственность производных классов" - это конечно круто звучит.
учитывая, что так можно обозвать
любое проявление динамического полиморфизма,
осуществляемого посредством виртуальных функций-членов.
3
4 / 4 / 3
Регистрация: 13.07.2014
Сообщений: 129
23.07.2015, 17:31  [ТС] 18
Большое всем спасибо!
0
23.07.2015, 17:31
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.07.2015, 17:31
Помогаю со студенческими работами здесь

Dynamic_cast и static_cast: в чём смысл?
Здравствуйте! Подскажите пожалуйста... В теории, как я понял, dynamic_cast является лишь...

В чем смысл заголовочных файлов?
Не понимаю в чем смысл заголовочных файлов,точнее даже не так. Вот к примеру если я пишу...

В чём смысл return в main()?
Есть ли смысл возвращать значение переменной в main()? Если да - зачем? #include&lt;iostream&gt;...

class classname; В чем смысл?
Доброго времени. Иногда встречается код типа: namespace Compiler { class Context; } ...


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

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