Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Подводные камни  (Прочитано 8030 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 21-04-2013 19:48 » 

Есть в C++ такая штука, как неопределённость приводимости типа в случае ромбовидного наследования:

Код: (C++)
struct A {};
struct I1 : public A {};
struct I2 : public A {};
struct B : public I1, public I2 {};

int main()
{
  B *b = new B();
  A *a = b; // error: ambiguous conversions from 'B *' to 'A *'
  A *a = reinterpret_cast<A *>(b); // OK
  return 0;
}
Ошибку сообщает компилятор, и она может решаться грубой силой - через reinterpret_cast.

Но компилятор ничего не скажет в случае подразумеваемого приведения:
Код: (C++)
try
{
  throw new B();
}
catch(A *a)
{
  // ожидаем попасть сюда, но фигушки!
  delete a;
}
catch(void *e)
{
  // мы сюда попадём
  delete e;
}

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

Мораль:
1) Не увлекаться наследованиями, особенно множественными, особенно с ромбовидной структурой иерархии.
2) Если невозможно, то управлять соответствием типов при помощи конструкций reinterpret_cast<A *>(new B()) и т.п.
3) Не передавать через механизм обработки исключений чего ни попадя, ограничиваясь специально созданными для этого классами и их объектами.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 21-04-2013 20:06 » 

А что на это говорят отцы?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #2 : 22-04-2013 03:44 » 

Dimka, CBuilder просто не дал скомпилировать строку

Код: (C++)
    throw new B();  // [C++ Error] xxx.cpp(122): E2018 Cannot throw 'B *' -- ambiguous base class 'A'

Вот описание из help
Цитата: ms-help://borland.bds4/bds4win32guide/html/errambigthrow.htm

It is not legal to throw a class that contains more than one copy of a (non-virtual) base class.


Типа две копии базового класса. В каком компиляторе работаешь?
« Последнее редактирование: 22-04-2013 03:46 от sss » Записан

while (8==8)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 22-04-2013 07:29 » 

Я тоже думаю, что это заморочки компилятора Студии. Даже, если попытаться поймать исключение типа прямых родителей I1,  I2:

Код: (C++)
        try
        {
                throw new B();
        }
        catch(A *a)
        {
                delete a;
        }
        catch(I1 *i1)
        {
                delete i1;
        }
        catch(I2 *i2)
        {
                delete i2;
        }
        catch(void *e)
        {
                delete e;
        }

то, несмотря на предупреждения:

warning C4286: 'I1 *' : is caught by base class ('A *')
warning C4286: 'I2 *' : is caught by base class ('A *')

попадаем в catch(I1 *i1)

Те, с одной строны, компилятор изначально думает правильно, но в итоге делает по-другому.
« Последнее редактирование: 22-04-2013 07:32 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines