当我像下面这样投射时,我会得到一些奇怪的东西。我的意图是得到这样的东西:
Inside Base
Inside Derived1
但是我获得了无数的“Inside Base”......这是代码:
#include <iostream>
using namespace std;
template<typename Derived>
class Base
{
public:
virtual void somefunc()
{
cout << "Inside Base\n";
static_cast<Derived*>(this)->somefunc();
}
};
class Derived1: public Base<Derived1>
{
public:
void somefunc()
{
cout << "Inside Derived1\n";
}
};
int main(int argc, char** argv)
{
Base<Derived1> b1;
b1.somefunc();
return 0;
}
答案 0 :(得分:1)
穆罕默德·阿里·贝敦(Mohammad Ali Baydoun)在关于当你演出时没有更新vtable的声明中是正确的。
当您在b1.somefunc()
中致电main
时,由于b1
是Base<Derived1>
,Base<Derived1>::somefunc()
将被调用。当您执行强制转换为Derived1
时,vtable不会更新,而您投射的对象仍然在内部Base<Derived1>
而不是Derived1
。 vtable查找导致另一次调用Base<Derived1>::somefunc()
而不是Derived1::somefunc()
,结果是无限递归。
然而,这是未定义的行为,因为您将基类对象转换为其不是的东西。将Derived1作为模板参数放置并不会使其定义为行为。
答案 1 :(得分:1)
您的代码有未定义的行为。这是一个简短的片段,原理相同:
struct Base { };
struct Derived: Base { int x; };
int main()
{
Base b;
static_cast<Derived &>(b).x = 5;
}
即使x
不存在,它仍未定义,但我添加它以帮助说明问题。您正在处理对象b
,但是内存中的行踪是5
被写入了吗?
规则是,如果您使用static_cast
从基类到派生类,则必须检查您正在投射的内容实际指向/引用该派生类的实例。如果它是,那么它的工作原理;如果不是那么它是无声的未定义行为。