gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:10:16 24 4
gpt4 key购买 nike

这个问题与这个问题非常相似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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com