在this answer中,出现了以下情况:
#include <cassert>
struct A {};
struct B { virtual ~B(){} };
struct AA{};
template <class T>
struct C : A, T {};
int main()
{
B * b = new C<B>;
AA * aa = new C<AA>;
assert(dynamic_cast<A*>(b));
assert(dynamic_cast<A*>(aa)); //this line doesn't compile, as expected
}
在g ++ 4.8.4(Ubuntu)上,这个编译并且断言传递。我的问题是,这真的合法吗?我觉得你根本不应该dynamic_cast
完成非多态的课程,但我承认我不是这里发生的事情的专家。
当我尝试相反的方向时:
dynamic_cast<B*>((A*)(new C<B>));
无法编译,声明“源类型不是多态的”。我觉得这是一个线索,但是找到属于当前指针所在的类的非多态基类似乎仍然是一个延伸(该句子是否有意义?)。
答案 0 :(得分:13)
是的,你可以。
正如§5.2.7/ 5中关于表达式dynamic_cast<T>(v)
的C ++标准所说:
如果
T
是“指向 cv1B
的指针”并且v
具有“指向 cv2的指针 {{1} “这样的话D
是B
的基类,结果是指向唯一D
的指针B
指向的D
对象的子对象。
也给出了一个例子:
v
正如您所看到的,多态类显然不是标准允许的struct B { };
struct D : B { };
void foo(D* dp) {
B* bp = dynamic_cast<B*>(dp); // equivalent to B* bp = dp;
}
的唯一用例。
顺便说一句,cppreference explains it用较少的标准语言:
如果 new_type 是Base的指针或引用,则类型为 expression 是Derived的指针或引用,其中Base是a Derived的唯一可访问基类,结果是指针或 引用Derived对象中的Base类子对象 由表达式指出或标识。 (注意:隐式演员和 static_cast也可以执行此转换。)