Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.96/67: Рейтинг темы: голосов - 67, средняя оценка - 4.96
Заблокирован

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

23.11.2011, 01:05. Показов 17169. Ответов 101
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Наткнулся в интернете на любопытный код.
Спешу поделиться с сообществом.
Просто, что бы кто если не в курсе - узнал, и не попал на эти грабли:


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
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.11.2011, 01:05
Ответы с готовыми решениями:

Неочевидные особенности выдачи pg таблиц
Я довольно много копаюсь в pg_* таблицах, дабы получать информацию о базе данных и прочих системных фишечках. Ближе к делу: ...

Неочевидные результаты очевидных css-свойств
Добрый вечер, господа верстальщики! Столкнулся с такой неочевидной для меня проблемой: Оказывается, добавив свойство padding:1px,...

Грабли с кодировкой
Здравствуйте! В конструкторе главного окна: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new...

101
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
18.12.2011, 13:45
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от 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; };
то будет в точности наоборот.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
22.10.2022, 10:40
Проблема не только в виртуальных таблицах. Проблема в том, что подобъекты базовых классов в наследнике типа T расположены по разным смещениям от начала объекта типа T. Смещение каждого зависит от порядка размещения и размера подобъектов. Указатель void указывает на первый байт объекта типа T и ни чего не знает о том в каком порядке объект типа T (про тип T он тоже не знает) унаследовал от некоторого множества (if any) предков. О размере предков он знает столько же. Вот почему, миной замедленного действия является С подход к С++. С каждым плюсом с языка сдирается целый слой кожи. С мясом. Извините за натурализм, но так - просто, выпукло и сжато.
ps я знаю, что тема древняя. Но вопрос интересен, а информации в доступной форме не слишком много.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.10.2022, 10:40

Xmega грабли
Так понимаю, мало кто в форуме xmega занимается, но вдруг кому полезно будет. Они, конечно, описаны в даташитах, но... Мелкие отличия...

Грабли с USART_FLAG_RXNE
Решил тут создать сообщение, чтобы поделиться ошибкой, что я ловил пол дня. Есть у арма регистр, куда падает приходящая инфа в УАРТ. ...

Наступлю на те же грабли?
Здравствуйте. Регистрировал доменное имя через jino.ru, а они согласно whois использовали R01-REG-RIPN. Потом выбрал другой хостинг....

Грабли с WM_DEVICECHANGE
Потратил кучу времени на изучение структур связанных с WM_DEVICECHANGE. Все работает как надо wParam == DBT_DEVICEARRIVAL , отлавливает...

Грабли malloc/free
С динамической памятью впервой работаю, от сюда и грабли Есть структура typedef struct { uint8_t data_size; uint8_t *data;...


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

Или воспользуйтесь поиском по форуму:
102
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru