cma*_*t85 6 c++ constructor dynamic-cast this multiple-inheritance
这个问题与这个问题非常相似为什么我不能在多重继承期间"动态地"广播"侧身"?,除了强制转换确实有效 - 只是不在构造函数内部.
标题:
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() {}
};
Run Code Online (Sandbox Code Playgroud)
资源:
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; }
Run Code Online (Sandbox Code Playgroud)
主要:
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;
}
Run Code Online (Sandbox Code Playgroud)
结果:
Printing C...
A
B
Checking again...
1
Run Code Online (Sandbox Code Playgroud)
因此,dynamic_cast确实适用于多重继承(没有意外!),但为什么不在运行时调用B :: B()中的'this'指针?我认为对象在构造函数体内完全形成,即所有内存都是为组件对象分配的,它们尚未初始化.我理解这取决于超类构造函数的顺序,但是在这个例子中,A在B之前被调用.
我显然不明白究竟发生了什么事情,有人可以赐教吗?
谢谢,Cam Bamber.
基本上标准说它在构造对象期间不起作用(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;
Run Code Online (Sandbox Code Playgroud)
额外的输出是:
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
Run Code Online (Sandbox Code Playgroud)
它在构造函数中失败,因为该对象未完全形成.使用这个,我们试图在C构造函数启动之前将C指针转换为B指针(用户定义的代码).因此,使用thisB :: B()作为指向C对象的指针会失败,因此当调用dynamic_cast <>时,由于UB而无法按照您的意愿执行操作.
第3段
显式或隐式地将引用类X的对象的指针(glvalue)转换为指向X的直接或间接基类B的指针(引用),构造X及其所有直接或间接基础的构造直接或间接从B派生的应该已经开始并且这些类的销毁不应该完成,否则转换会导致不确定的行为.要形成指向对象obj的直接非静态成员(或访问其值)的指针,obj的构造应该已经开始并且它的销毁不应该完成,否则计算指针值(或访问成员) value)导致未定义的行为.
[例如:
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
}
};
Run Code Online (Sandbox Code Playgroud)
- 结束例子]
</报价>