C++ 通过基指针将派生类强制转换到其中一个基
编辑:好的,正如我现在看到的,这会改变很多情况,因此更精确的情况如下: 我目前的层次结构与此类似:C++ 通过基指针将派生类强制转换到其中一个基,c++,inheritance,upcasting,C++,Inheritance,Upcasting,编辑:好的,正如我现在看到的,这会改变很多情况,因此更精确的情况如下: 我目前的层次结构与此类似: 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 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...>();
通过派生调用IBase接口的所有调用都可以正常工作,但当我尝试将派生转换为IDerived时,调用任何函数都会出错:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.
IDerived* d = (IDerived*)derived;
d->Bar(); <- boom error ;)
IDerived*d=(IDerived*)派生;
d->Bar() 您正在执行交叉播放IBase
和IDerived
是不相关的。您需要先强制转换为派生的
,然后再转换为IDerived的
。如果您使用的是static\u cast
而不是C cast,编译器会在编译时为您捕捉到这一点
我假设您知道,IBase
实际上是一个派生的
,因为您使用了C转换,但是如果您不这样做,那么您也可以使用dynamic_cast
安全地执行交叉转换
编辑:如果您不能使用RTTI并且不知道对象的动态类型,那么虚拟继承和dynamic\u cast
将退出窗口。当您调用CreateDerived
时,看起来您确实知道对象的动态类型(因为它的模板参数),因此您可以有一个std::map
,然后在CreateDerived()之后
call您可以static\u cast
将IBase*
转换为Derived*
,然后将指针作为键和值插入到映射中
只需启用RTTI;这越来越复杂了<代码>IDerived*d=(IDerived*)d代码>-输入错误?第二个d
应该是派生的吗?
谢谢,alredy注意到了这一点并修复了;)此外,C++中不应该使用C风格的转换,而是使用C++风格的转换,如<代码> StasyType > <代码>或<代码> Dyjic Skys> /Cord>,这是最后一次编辑后的一个全新问题!是的,很抱歉我忽略了角色模板在这里的作用。就像我说的,我讨厌所有那些奇怪的复杂的解决方案。在这种情况下,我看不到更好的选择。谢谢你的回答,但这不是那么简单,我应该从一开始就澄清;)请看地图edit@AdrianLis如果您不能使用dynamic_cast
,那么从IBase
到IDerived
通常是没有安全的方法的。感谢您的提示,我将研究EDIT2建议,看看它是否解决了更大规模场景中的问题;)我会让你知道,从非常简短的测试,似乎中级班解决了这个问题。目前还不确定它将如何与样板文件的其余部分一起进行,但肯定它解决了所描述的问题,因此我将您的答案标记为解决方案。谢谢;)
class IBase { virtual void Foo() = 0; };
class Base : public IBase { virtual void Foo() { } };
class IDerived { virtual void Bar() = 0; };
class BaseAndDerived : public Base, public IDerived { };
template<typename TT, typename TB, typename... TI>
class Derived : public BaseAndDerived { virtual void Bar() {}};