EDIT: Ok as I see now this changes the case a lot so the more precise scenario is as such:
The hierarchy I currently have is somewhat similar to this:
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...>();
I am getting error with Visual Studio while trying to cast an object and call a function:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
All calls of IBase interface through derived work fine but when I try to cast derived to IDerived I get the error calling any function:
IDerived* d = (IDerived*)derived;
d->Bar(); <- boom error ;)
I guess that such cast is illegal but how can I cast the pointer so that I can get access to IDerived interface methods (preferably without dynamic_cast I would prefer a good and portable hack if one exists ;))? Is it possible somehow to calculate offset to the pointer so that the proper vtable is used and everything works as it should ?
I am programming for quite a long time but I always dodged all those fancy-shmancy over engineered systems with tons of interfaces and templates and now I am doomed to make one myself.
EDIT: Now as you can see this gets tricky and difficult. I don't know the exact type of the Derived I am getting as it is templated, also the function CreateDerived is templated and returns interface.
Also, one of the requirements is not to use dynamic_cast (RTTI is disabled in the project)
You are performing a cross-cast;
IBaseandIDerivedare unrelated. You need to cast toDerivedfirst and then toIDerived. If you used astatic_castrather than a C cast the compiler would have caught this for you at compile-time.I assume you know that the
IBaseis really aDerivedbecause you used a C cast, but if you don't then you can also usedynamic_castto perform cross-casts safely.EDIT: If you can't use RTTI and you don't know the dynamic type of the object then virtual inheritance and
dynamic_castgo out of the window. When you callCreateDerivedit looks like you do know the dynamic type of the object (because of its template arguments) so you could have astd::map<IBase*, IDerived*>and then after theCreateDerived<TT, TB, TI...>()call you canstatic_casttheIBase*toDerived<TT, TB, TI...>*and then insert the pointer as both the key and value into the map.Just enable RTTI; this is getting complicated. >.<
EDIT 2: Alternatively, you seem to know that the object pointed at by the
IBase*does also derive fromIDerived*. If you can modify the class hierarchy you can have an abstract base class that derives from bothIBaseandIDerivedand then haveDerivedderive from this new base class. Then you canstatic_castfrom anIBase*to the new class in the hierarchy and then toIDerived*.It would look something like this: