Войти
ПрограммированиеФорумОбщее

С++ баг!! стандартный или MS-specific ? (3 стр)

Advanced: Тема повышенной сложности или важная.

Страницы: 1 2 3 4 5 6 7 Следующая »
#30
17:07, 8 фев. 2010

vonrims
> А что бы Вы, уважаемый, таки, ожидали в таком случае:
в таком случае компилятор выдаст ошибку. но надо заметить, что этот случай абсолютно бессмысленный - попробуйте подогнать под него хоть какую-то осмысленную задачу.vonrims

> Вы попробуйте IObject привести к ObjectImp
даункаст - зло =)) ходят слухи, что при правильном проектировании необходимости в нем нету =)) (лично у меня даункаст только в качестве костылей, и то раз два и обчелся)


#31
17:27, 8 фев. 2010

vonrims
> Если это не так, то подобных граблей на вашем пути предостаточно.
даунткаст - и есть грабли.
приводя IObject к ObjectImp компилятор не может нас защитить от того, что указатель является указателем на ObjectImp. а dynamic_cast в данном случае - просто костыль.
а где грабли в моем коде? из 0го поста?

#32
17:29, 8 фев. 2010

vonrims
> Виртуальное наследование - зло палюбому.
виртуальное наследование - это красивое решение для некотрых задач. зло оно для того, кто им пользоваться не умеет =))

#33
19:25, 8 фев. 2010

Ктоэто тут в моей теме самовольно посты удаляет?

#34
19:45, 8 фев. 2010

Kloun
> виртуальное наследование - это красивое решение для некотрых задач. зло оно для того, кто им пользоваться не умеет
опять же, виртуальное наследование - это инструмент. существуют задачи, которые с его помощью решаются достаточно хорошо. у этого инструмента, как у большинства других, есть особенность - при неумелом его использовании(даункаст, например), результат получается не идеальный. в этом есть что-то удивительное?

#35
20:26, 8 фев. 2010

Suslik
> в этом есть что-то удивительное?
все правильно говоришь. У меня в коде есть даункаст? только апкаст и тот не явный - на совести компилятора (он то какраз и не сработал)
если для моей задачи не подходит виртуальное наследование - я рад выслушать альтернативное решение!!!!!

#36
20:34, 8 фев. 2010

Kloun
> виртуальное наследование - это красивое решение для некотрых задач. зло оно для
> того, кто им пользоваться не умеет =))

Множественное наследование вообще и виртуальное множественное наследование в частности - клёвые фичи, которые были придуманы не потому что нужны, а потому что непонятно было нужны ли. Поддерживаются патамушта стандарт.

Например, в C# в чистом виде нет ни того, ни другого. Есть множественное наследование интерфейсов, что решает все грабли разом.

Т.е., ИМО, зло оно, всвязи с:
  - всегда можно и без...
  - если с вашим кодом можете работать только вы (ну или узкий круг профи)... то это не самый лучший код в мире. Далеко не все знают достаточно о виртуальном наследовании. В частности, по сабжу только домыслы выше по тексту.
  - если в вашем коде встречаются траблы, возникшие из-за разницы реализации в компиляторах спорной ситуации... виноват, полагаю, не компилятор.
  - если некоторый код может выполняться медленней из-за виртуального наследования, то такой выбор не из лучших.

#37
20:39, 8 фев. 2010

Я официально признаю, что не знаю, как точно работает виртуальное наследование в некоторых случаях. Поэтому я его использую только для виртуального наследования интерфейсов и мои волосы мягкие и шелковистые. Собственно, в других языках(джава, сишарп), есть только такая возможность и я ни разу не встречал, что кто-то горевал из-за отсутствия возможности виртуального множественного наследования от классов с данными.

#38
20:41, 8 фев. 2010

Kloun
> только апкаст и тот не явный - на совести компилятора (он то какраз и не
> сработал)

Так не про апкаст речь в данном раскладе.
Получаем 2 виртуальные таблицы от 2-х базовых классов. Компилятор не обязан за вас решать по какой ветке подниматься при поиске имени. Иначе, это получается магия сравнимая с dynamic_cast, т.е. проверка всех веток слева-направо и выбор первой попавшейся реализации в рантайме.
MSVC берёт указатель из виртуальной таблицы первого базового класса и натыкается на вилы.
Что при этом делает gcc - загадка. Попробуйте померять производительность в случае обычного виртуального вызова и такой хитрой ситуации.

#39
20:44, 8 фев. 2010

innuendo
> level 4 - это конечно мазохизм.
Я мазохист о_О

#40
21:11, 8 фев. 2010

Suslik
ХМ, т.е. если я из самого базового класса уберу реализацию и перенесу ее ниже по иерархии (всеравно объекты толка в двиге создаются, да и инлайны в том случае не ахти какая нужная вещь) то проблема ичезнет? т.е. базовый класс IObject станет чисто виртуальным

vonrims
> Так не про апкаст речь в данном раскладе.
вообщето речь какраз о неявном апкасте в моем коде - он и не работает. для обхода этого ньюанса не нужна магия с динамик кастом, компилятор вполне может решить проблему также, как ее решил я (по все видимости гцц именно так и поступает) либо в крайнем случае компилятор должен выдать ошибку (он ее может обнаружить!!! более того, в том месте, где он ее должен обнаруживать, у него стоит проверка, если я возвращаемое значение поставлю вообще левое , например инт, он же ругнется, хоть виртуальное наследование там хоть нет!)

> Компилятор не обязан за вас решать по какой ветке подниматься при поиске имени
вот когда компилятор создает таблицу виртуальных функций для ObjectImp - он видит, что метод create перегружен по возвращаемому значению, сталобыть для виртуальной таблицы которая используется в IObject, он должен поставить указатель не на реальный метод а на некотрый прокси, который сделает апкаст для возвращаемого значения. насколько я понимаю, такое возможно, (по крайней мере под отладчиком виртуальные таблицы разные на одном и томже объекте, в зависимости от того ссылка на IObject или на ObjectImp)

#41
0:05, 9 фев. 2010

Kloun
Для компилятора нету криминала в этом коде.
Он видит реализацию всех методов. И в производном классе реально будут все реализации. Но ссылки на функции будут находиться в разных таблицах виртуальных методов. Это грабли множественного наследования. Порядок конструкторов определяет, какая таблица виртуальных функций будет на переднем крае. Т.е. сначала вызывается конструктор IObject, затем IObjectModel, они собирают таблицу виртуальных методов ObjectModelImp, затем вызывается конструктор ObjectImp, у которого базовая виртуальная таблица собрана при конструировании IObject + свои виртуальные методы. Но это отдельная таблица.

> (по крайней мере под отладчиком виртуальные таблицы разные на одном и томже
> объекте, в зависимости от того ссылка на IObject или на ObjectImp)

Воистину, так. Это 2 разных объекта, сшитых "перемычкой" по определённым правилам.

Когда происходит вызов, код MSVC по-честному вызывает метод из таблицы виртуальных методов ObjectModelImp (IObject + IObjectModel). И получает по лбу. Почему MSVC не генерит кода, который порешает эту проблему? Ну, например, я против того, чтоб этот код был сгенерён. Лучше перепроектировать такой кусок системы, чем жить на потенциальной бомбе.
Что для MSVC может порешать эти грабли? Если у вас отключен RTTI, включите. Может и заработает. Но уж лучьше ну его нафиг.

Что делает gcc? Всё очень просто: если на момент компиляции известен конечный тип, вызов может встроиться (за счет оптимизаций), если конечный тип может быть определён только рантайм, происходит такой же вызов как и в коде MSVC, но, например, стоит отлов эксепшенов (ну или тупо проверка на NULL). Если вызов не прокатил с диагнозом pure virtual call, рантайм пытается перепрыгнуть в другую виртуальную таблицу при помощи RTTI. Компилятор считает, что раз класс можно собрать, то и вызов должен прокатить железно. Это работает, как вы понимаете, несколько медленнее обычного виртуального вызова.

#42
0:19, 9 фев. 2010

Кстати, при множественном наследовании (невиртуальном) без RTTI такие штуки и в gcc, скорее всего работать не будут. Там уже никто по базовому классу не сможет определить какие есть ветки наследования и как по ним подниматься. В данном случае, не удастся даже IObject привести к ObjectModelImp без dynamic_cast. Так как никому не известно чей в данном случае родитель IObject: IObjectModel или ObjectImp.
А вызов одного и того же метода у разных IObject (родителя IObjectModel или родителя ObjectImp) может быть вызовом разных реализаций из IObjectModel и ObjectImp, соответственно.

Моё мнение: множественное наследование - зло.
Просто потому, что его контроллировать непросто. А непреднамеренно сломать поведение отдельного объекта или всего приложения, может даже "гуру", написавший такой код.

#43
0:23, 9 фев. 2010

Phuntik
> Я мазохист о_О
Ты не один. Нас много.
Нередко варнинг 3-его уровня в рантайме превлащается в ошибку. Усечения, сравнения знаковых с беззнаковыми и прочее могут ломать логику.

#44
2:41, 9 фев. 2010

vonrims
> Нередко варнинг 3-его уровня в рантайме превлащается в ошибку.
У меня по умолчанию стоит 4-й уровень. Ни одного варнинга. ЧЯДНТ? :)

Страницы: 1 2 3 4 5 6 7 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.