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;
IBase
andIDerived
are unrelated. You need to cast toDerived
first and then toIDerived
. If you used astatic_cast
rather than a C cast the compiler would have caught this for you at compile-time.I assume you know that the
IBase
is really aDerived
because you used a C cast, but if you don't then you can also usedynamic_cast
to 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_cast
go out of the window. When you callCreateDerived
it 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_cast
theIBase*
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 bothIBase
andIDerived
and then haveDerived
derive from this new base class. Then you canstatic_cast
from anIBase*
to the new class in the hierarchy and then toIDerived*
.It would look something like this: