c++ - 构造函数内部 "this"的 dynamic_cast

标签 c++ constructor this multiple-inheritance dynamic-cast

这个问题与这个问题非常相似Why can't I dynamic_cast "sideways" during multiple inheritence? ,除了强制转换确实有效 - 只是不在构造函数中。

标题:

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; }

主要内容:

int main( int argc, char* argv[] )
{
    cout << "Printing C..." << endl;
    C c;
    c.printA();
    c.printB();

    cout << "Checking again..." << endl;
    cout << !!dynamic_cast< A* >( &c ) << endl;

    return EXIT_SUCCESS;
}

结果:

Printing C...
A
B
Checking again...
1

所以,dynamic_cast 确实适用于多重继承(这并不奇怪!),但为什么在运行时为 B::B() 中的“this”指针调用时不能呢?我认为一旦在构造函数体内,对象就完全形成了,即所有内存都分配给了组件对象,它们还没有被初始化。我明白这取决于父类(super class)构造函数的顺序,但在此示例中,A 在 B 之前被调用。

我显然不明白引擎盖下到底发生了什么,有人可以启发我吗?

谢谢, 凸轮类伯。

最佳答案

基本上,标准表示在对象构造期间它不会工作 (dynamic_cast)。 <引用>

编辑:根据下面的 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;

额外的输出是:

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

它在构造函数中失败,因为对象没有完全形成。使用它,我们试图在 C 构造函数启动(用户定义的代码)之前将 C 指针转换为 B 指针。因此,在 B::B() 中使用 this 作为指向 C 对象的指针会失败,因此当 dynamic_cast<> 被调用时,由于 UB,它无法执行您想要的操作。

12.7 构造与销毁[class.cdtor]

第 3 段

To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or access the value of) a direct non-static member of an object obj, the construction of obj shall have started and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing the member value) results in undefined behavior.

[示例:

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
      } 
};

——结束示例]

关于c++ - 构造函数内部 "this"的 dynamic_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6299266/

相关文章:

javascript - 如何在父级的内部 div 上使用 "this"

C++从txt文件读取到对象二叉树

c++ - 在 C++ 中编写命令行界面的更好方法是什么?

typescript - 获取函数/类构造函数的参数类型

jquery 多个选择器,包括 'this' - 最佳干净语法

javascript - 使用这个。在 javascript 对象定义中

c++ - 如何在 C++ 中将 cout 更改为 printf?或者如何使控制台应用程序运行得更快?

c++ - POCO C++ 对象到 JSON 字符串序列化

c++ - 我只是在查看模板并在我的书中找到了这段代码,这显示了段错误?

javascript - 试图模拟 'new' 运算符