РЕДАКТИРОВАТЬ: Хорошо, как я теперь вижу, это сильно меняет случай, поэтому более точный сценарий таков:
Текущая иерархия в чем-то похожа на эту:
class IBase() { virtual void Foo() = 0; };
class Base() : public IBase { virtual void Foo() { } };
class IDerived() { virtual void Bar() = 0; };
template<typename TT, typename TB, typename... TI>
class Derived : public Base, public IDerived { virtual void Bar() {}};
template<typename TT, typename TB, typename... TI>
IBase* CreateDerived() { return new Derived(); }
IBase* derived = CreateDerived<some types...>();
Я получаю сообщение об ошибке в Visual Studio при попытке создать объект и вызвать функцию:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
Все вызовы интерфейса IBase через производные работают нормально, но когда я пытаюсь преобразовать производные в IDerived, я получаю сообщение об ошибке при вызове любой функции:
IDerived* d = (IDerived*)derived;
d->Bar(); <- boom error ;)
Я предполагаю, что такое приведение является незаконным, но как я могу указать указатель, чтобы получить доступ к методам интерфейса IDerived (желательно без dynamic_cast, я бы предпочел хороший и переносимый хак, если он существует;))? Можно ли как-то рассчитать смещение до указателя, чтобы использовалась правильная vtable и все работало как надо?
Я занимаюсь программированием довольно давно, но я всегда избегал всей этой изворотливости по сравнению со спроектированными системами с множеством интерфейсов и шаблонов, и теперь я обречен сделать один из них сам.
РЕДАКТИРОВАТЬ: Теперь, как вы можете видеть, это становится сложно и сложно. Я не знаю точного типа производного, который я получаю, поскольку он шаблонный, а также функция CreateDerived шаблонная и возвращает интерфейс.
Также одно из требований - не использовать dynamic_cast (в проекте отключен RTTI)
IDerived* d = (IDerived*)d;
- опечатка? должен ли второйd
бытьderived
вместо этого? - person SingerOfTheFall   schedule 13.09.2013static_cast
илиdynamic_cast
- person SingerOfTheFall   schedule 13.09.2013Derived*
вместоIDerived*
.IDerived
не является потомкомIBase
, аDerived
является потомком. - person SingerOfTheFall   schedule 13.09.2013dynamic_cast
, поэтому виртуальное наследование не помогает. - person Simple   schedule 13.09.2013IBase*
наDerived*
безdynamic_cast
, когдаIBase
- виртуальная база? Вы не можете использоватьstatic_cast
, потому что смещения неизвестны во время компиляции. - person Simple   schedule 13.09.2013reinterpret_cast
- person SingerOfTheFall   schedule 13.09.2013reinterpret_cast
небезопасен, потому чтоDerived*
будет указывать на неправильный адрес. - person Simple   schedule 13.09.2013reinterpret_cast
, поэтому оба они плохие. - person Simple   schedule 13.09.2013