C++ 动态“U型铸造”;这";内部构造函数

C++ 动态“U型铸造”;这";内部构造函数,c++,constructor,this,multiple-inheritance,dynamic-cast,C++,Constructor,This,Multiple Inheritance,Dynamic Cast,这个问题与这个问题非常相似,只是cast可以工作——只是不能在构造函数内部工作 标题: class A { public: virtual ~A() {} void printA(); }; class B { public: B(); virtual ~B() {} void

这个问题与这个问题非常相似,只是cast可以工作——只是不能在构造函数内部工作

标题:

class A  
{  
public:  
    virtual                ~A() {}
    void                    printA();
};

class B
{
public:
                            B();
    virtual                ~B() {}
    void                    printB();

private:
    std::string             message_;
};

class C : public A, public B
{
public:
                        C() {}
    virtual                ~C() {}
};
资料来源:

void A::printA() { cout << "A" << endl; }
B::B()
{
    A* a = dynamic_cast< A* >( this );
    if ( a ) {
        message_ = std::string( "A and B" );
    } else {
        message_ = std::string( "B" );
    }
}
void B::printB() { cout << message_.c_str() << endl; }
因此,动态_cast确实适用于多重继承(这并不奇怪!),但是为什么在运行时为B::B()中的“this”指针调用时不能呢?我认为,一旦在构造函数主体内,对象就完全形成了,即所有内存都分配给了组件对象,它们还没有初始化。我知道这取决于超类构造函数的顺序,但在本例中,在B之前调用A

我显然不明白引擎盖下到底发生了什么,有人能告诉我吗

谢谢,
Cam Bamber.

在构建
A
时,动态类型为
A
。这是因为在构造派生类之前,您将开始调用派生类的成员函数并访问派生成员变量,这将是非常糟糕的。

因为
B
不继承自
A
B
是最父类),
B
在其构造过程中的动态类型是
B
。只有同时构造父级
A
B
时,才能构造子级
C
,允许横向
动态转换
ing。

它在B内部不工作,因为B不是从A继承的,每个基类构造函数都是在派生类构造函数之前执行的,在
B
构造函数中,对象的动态类型为
B
;在您输入
C
构造函数之前,它不会成为
C
。因此,您不能执行任何需要动态类型
C
的操作:您不能交叉转换到
C
的任何其他基类,并且如果您调用了虚拟函数,那么您将不会得到
C
提供的任何重写


在引擎盖下,动态类型(至少在大多数实现中)由对象中的指针(称为“vptr”)确定,该指针指向指定类属性的一些静态数据,包括虚拟函数表(称为“vtable”)以及
dynamic\u cast
typeid
所需的信息。在每个构造函数之前,它都会被更新,以指向当前正在构造的类的信息。

基本上,标准说它在对象构造期间不起作用(动态转换)。

编辑:根据下面的VJo注释添加

注意:使用动态强制转换从“B”到“a”的强制转换应该可以工作,因为我们正在强制转换类型为“C”的对象。如果我们将以下代码添加到main:

B  bObj;
B& bRef = c;
B* bPtr = &c;
std::cout << !!dynamic_cast<A*>(&bObj) << std::endl;
std::cout << !!dynamic_cast<A*>(&bRef) << std::endl;
std::cout << !!dynamic_cast<A*>( bPtr) << std::endl;
-[结束示例]


我担心事实上,这与此无关。@DeadMG为什么<代码>动态_cast(此)返回NULL,因为它不应该与引用标准争论@尤其是当它是一个错误的段落时。类A不是类的基类B@VJo:我假设您认为以下操作会失败:
B&bref=c;不,那(在你的编辑中)是因为你所说的原因而起作用的。顺便说一句,在你的编辑很好的解释。“在每个构造函数之前”实际上是在构造基本对象之后,在构造或初始化成员变量之前
Printing C...
A
B
Checking again...
1
B  bObj;
B& bRef = c;
B* bPtr = &c;
std::cout << !!dynamic_cast<A*>(&bObj) << std::endl;
std::cout << !!dynamic_cast<A*>(&bRef) << std::endl;
std::cout << !!dynamic_cast<A*>( bPtr) << std::endl;
0   // Can not convert a B to an A
1   // Can convert this B to an A because it is really a C.
1   // This is  what we are reeling doing in B::B() that fails
    // It is not the dynamic_cast<> that fails but the conversion of this from C* to B*
    // That is causing UB
struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };
struct E : C, D, X 
{ 
    E() : D(this),  // undefined: upcast from E* to A*
                    // might use path E* → D* → A* 
                    // but D is not constructed 
                    // D((C*)this), 
                    // defined: 
                    // E* → C* defined because E() has started 
                    // and C* → A* defined because
                    // C fully constructed 
      X(this) { // defined: upon construction of X,
                    // C/B/D/A sublattice is fully constructed
      } 
};