Форум программистов, компьютерный форум CyberForum.ru

Неочевидные грабли полиморфизма с++ - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 52, средняя оценка - 4.79
Bers
Заблокирован
23.11.2011, 01:05     Неочевидные грабли полиморфизма с++ #1
Наткнулся в интернете на любопытный код.
Спешу поделиться с сообществом.
Просто, что бы кто если не в курсе - узнал, и не попал на эти грабли:


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>
using namespace std;
 
struct A
{
    virtual void Func1(){cout<<"A::Func1"<<endl;}
};
struct B
{ 
    virtual void Func2(){cout<<"B::Func2"<<endl;}}
;
struct C: public A, public B
{ 
    virtual void Func3(){cout<<"C::Func3"<<endl;}
};
 
int main()
{
    A *ptr = new C;
    void *ptr1 = new C;
    
    ((A*)ptr)->Func1(); //вывод: A::Func1
    ((B*)ptr)->Func2(); //вывод: A::Func1 Почему?
    ((C*)ptr)->Func3(); //вывод: C::Func3
    
    A* aPtr=dynamic_cast<A*>(ptr);
    B* bPtr=dynamic_cast<B*>(ptr);
    C* cPtr=dynamic_cast<C*>(ptr)
    
    //нельзя кастовать от void*
    //void* ничего не знает ни о каких классах
    //и ни о каких таблицах виртуальных функций
 
    C* cPtr=dynamic_cast<C*>(ptr1); //ошибка компиляции
    //error C2681: void *: недопустимый тип выражения для dynamic_cast
    
    aPtr->Func1(); //вывод: A::Func1
    bPtr->Func2(); //вывод: B::Func2
    cPtr->Func3(); //вывод: C::Func3
 
    delete ptr;
    delete ptr1;
 
    return 0;
}
От себя могу добавить, что разные компиляторы по разному могут реализовывать механизм полиморфизма. Поэтому, при множественном наследовании если что и спасет - только dynamic_cast
Но в любом случае, нужно быть предельно осторожным.

А по сути, полиморфизм + множественное наследование = мина замедленного действия.

Поэтому, при проектировании полиморфных классов, лучше до последнего избегать множественного наследования.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.11.2011, 01:05     Неочевидные грабли полиморфизма с++
Посмотрите здесь:

C++ Использование полиморфизма
Модификатор const Очередные грабли с++? C++
C++ Реализация полиморфизма
C++ иллюстрация полиморфизма
Виды полиморфизма C++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.12.2011, 13:45     Неочевидные грабли полиморфизма с++
Еще ссылки по теме:

В чем смысл полиморфизма C++
C++ Использование свойств полиморфизма
Смысл использования полиморфизма C++

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

Или воспользуйтесь поиском по форуму:
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
18.12.2011, 13:45     Неочевидные грабли полиморфизма с++ #101
Цитата Сообщение от alexzak Посмотреть сообщение
Очевидно, это не так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cstdio>
#include <cassert>
 
class A { int a; };
class B { int b; };
class C : public A, public B { int c; };
 
int main()
{
    C obj;
    A * a = &obj;
    B * b = &obj;
    C * c = &obj;
 
    std::printf("a != b                       : a = %p, b = %p, c = %p\n", a, b, c);
    std::printf("(C *)a == (C *)b             : (C *)a = %p, (C *)b = %p\n", (C *)a, (C *)b);
    std::printf("static cast (C *)a == (C *)b : (C *)a = %p, (C *)b = %p\n", static_cast<C *>(a), static_cast<C *>(b));
 
    assert((C *) a == (C *) b);
    assert(static_cast<C *>(a) == static_cast<C *>(b));
}
При преобразовании (C*)b происходит поправка значения указателя.
Да, здесь указатель на B показывает положение B "внутри" С. Если мы поменяем порядок наследования:
C++
1
class C : public B, public A  { int c; };
то будет в точности наоборот.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Yandex
Объявления
18.12.2011, 13:45     Неочевидные грабли полиморфизма с++
Ответ Создать тему
Опции темы

Текущее время: 00:05. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru