奇怪的铸造产品

Weird product of casting

本文关键字:      更新时间:2023-10-16

当我像下面这样投射时,我得到了一些奇怪的东西。我的目的是得到这样的东西:

Inside Base
Inside Derived1

但我得到了无限数量的"内部基地"...这是代码:

#include <iostream>
using namespace std;
template<typename Derived>
class Base
{
public:
    virtual void somefunc()
    {
        cout << "Inside Basen";
        static_cast<Derived*>(this)->somefunc();
    }
};
class Derived1: public Base<Derived1>
{
public:
    void somefunc()
    {
        cout << "Inside Derived1n";
    }
};
int main(int argc, char** argv)
{
    Base<Derived1> b1;
    b1.somefunc();
    return 0;
}

您的代码具有未定义的行为。下面是一个具有相同原理的较短片段:

struct Base { };
struct Derived: Base { int x; };
int main()
{
    Base b;
    static_cast<Derived &>(b).x = 5;
}

即使不存在x它仍然未定义,但我添加了它以帮助说明问题。您正在处理对象b但是内存中的下落5正在写入吗?

规则是,如果您使用从基类到派生类的static_cast大小写,则必须检查您正在转换的东西是否实际指向/引用该派生类的实例。如果是,那么它就可以工作;如果不是,那么它是无声的未定义行为。

Mohammad Ali Baydoun关于执行演员表时vtable未更新的陈述是正确的。

当你在main中呼唤b1.somefunc()时,因为b1是一个Base<Derived1>Base<Derived1>::somefunc()会被召唤。当您执行强制转换以Derived1 时,vtable 不会更新,并且要转换的对象在内部仍然是Base<Derived1>而不是Derived1。vtable 查找会导致对 Base<Derived1>::somefunc() 的另一个调用而不是Derived1::somefunc(),结果是无限递归。

但是,这是未定义的行为,因为您要将基类对象强制转换为它不是的东西。 将 Derived1 作为模板参数不会使其成为定义的行为。

相关文章:
  • 没有找到相关文章