来自https://en.cppreference.com/w/cpp/language/dynamic_cast:
dynamic_cast < new_type > ( expression )
3)如果
new_type
是对Base的指针或引用,而expression
的类型是对Derived的指针或引用,其中Base是唯一,可访问派生基类的结果,结果是指向expression
指向或标识的派生对象中基类子对象的指针或引用。 (注意:隐式转换和static_cast
也可以执行此转换。)
示例代码:
#include <iostream>
using namespace std;
class A {
//public:
// virtual ~A() {
//
// }
};
class B : public A {
};
class C : public B {
};
class D : public B, public A {
};
int main()
{
D* pd = new D;
if (B* pa = dynamic_cast<B*>(pd)) {
cout << "1";
}
return 0;
}
在VC ++下没有错误或警告
warning: direct base 'A' inaccessible in 'D' due to ambiguity
在gcc下,link
我不应该期待编译错误吗?
现在我发现,如果尝试将D*
转换为A*
,将会发生错误,但是如上所述,从D*
转换为B*
不会出错。
int main()
{
D* pd = new D;
if (A* pa = dynamic_cast<A*>(pd)) {
cout << "1";
}
return 0;
}
答案 0 :(得分:3)
在这种情况下,唯一表示派生的包含 new_type
一次,而不是派生的来自单个基类。
因此,在您的示例中,B
是唯一的,因为D
仅包含一次。
在您的示例中,D
包含 A
两次(直接一次,一次通过B
),因此无法强制转换为A
A
不是唯一的。
请注意,“包容”很重要。因此,在此示例中,C
两次从Base
派生,这很好,因为Base
是用关键字virtual
继承的:
struct Base { };
struct A: virtual Base { };
struct B: virtual Base { };
struct C: A, B { };
int main() {
C c;
dynamic_cast<Base &>(c);
}
(如果我没有使用过virtual
,那么Base
将会是模棱两可的)
注意:我会改用static_cast
,因为在这种情况下它也可以执行强制转换。在这里使用dynamic_cast
有点误导,因为转换将在编译时完成,而不是在运行时完成。
答案 1 :(得分:0)
警告是由多重继承模型中的间接基类问题引起的。 D
具有基类A
的两个副本,一个直接复制,一个通过B
间接复制。将基类指定为虚拟基类(与@geza示例相同)时,虚拟基类之间仅共享一个基类数据成员的副本。
class A {
public:
A() {}
};
class B : virtual public A {
public:
B() : A() {}
};
class C : public B, virtual public A {
public:
C() : B() {}
};
int main()
{
A* pa = static_cast<A *>(new C()); // no more warning since A is virtual
return 0;
}
在这里有很好的解释:Multiple Base Classes。