C++ 动态“U型铸造”;这";内部构造函数
这个问题与这个问题非常相似,只是cast可以工作——只是不能在构造函数内部工作 标题: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
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(此)在B的构造函数中,code>返回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
}
};