CODE
struct A { }; // virtual details there, but left out
struct B { }; // virtual details there, but left out
struct C : A, B { }; // virtual details there, but left out
C c;
B& b = c;
A& a = dynamic_cast<A&>( b ); // will this cast succeed at run-time?
请注意,我遗漏了虚拟细节以保持代码简单。
如果dynamic_cast&lt;&gt;仅限于继承层次结构中的直接强制转换,然后我希望上面的代码在运行时失败(因为B&amp;与A&amp;无关)。
但是,如果它更通用/更灵活,则代码应该起作用,因为引用对象的真实类型是C类型(并且C可以称为B&amp;或A&amp;)。
C ++规范对此案例的评价是什么?
答案 0 :(得分:6)
dynamic_cast<T>(v)
可以归结为v
是子对象的最派生对象,然后向上(可能是不同的分支)以找到T
的明确基类是指针或引用。从标准:
5.2.7 / 8 如果
C
是T
指向或引用的类类型,则运行时检查按逻辑执行如下:
- 如果在
v
指向(引用)的最派生对象中,v
指向(引用)C
对象的公共基类子对象,并且 如果只有一个C
类型的对象是从指向的子对象派生的 (引用)v
结果点(引用)C
对象。- 否则,如果
v
指向(引用)最派生对象的公共基类子对象,以及最派生对象的类型 有一个类型为C
的基类,它是明确的,公开的, 结果点(引用)到派生最多的C
子对象 对象。- 否则,运行时检查将失败。
答案 1 :(得分:3)
目前,代码无法编译,因为没有类具有任何虚函数 - 需要使用dynamic_cast
。如果您添加至少一个虚拟函数(例如,虚拟dtor到B
),则是,因为C
是从B
公开派生的,所以演员会成功。
以下是一些快速演示代码:
#include <iostream>
struct A {
virtual void junk() { std::cout << "A"; }
void trash() { std::cout << "A"; }
virtual ~A() {}
};
struct B {
virtual ~B(){}
void trash() { std::cout << "B"; }
void junk() { std::cout << "B"; }
};
struct C : virtual A, virtual B {
void trash() { std::cout << "C"; }
void junk() { std::cout << "C"; }
};
int main() {
C c;
B& b = c;
A& a = dynamic_cast<A&>(b);
a.trash();
std::cout << "\n";
a.junk();
}
输出(使用VC ++和g ++,这不是最先进的,所以我希望除了真正古老的编译器以外的任何东西都能正确):
A
C
显示a
的静态类型为A
,但动态类型为C
。