C++ c++;在运行时检查对象是否实现了接口
前段时间我问过这些问题: 但我仍然不确定我是否理解答案问题是:下面的代码有效吗?C++ c++;在运行时检查对象是否实现了接口,c++,casting,multiple-inheritance,C++,Casting,Multiple Inheritance,前段时间我问过这些问题: 但我仍然不确定我是否理解答案问题是:下面的代码有效吗? #include <iostream> using namespace std; struct Base { virtual void printName() { cout << "Base" << endl; } }; struct Interface { virtual void foo() {
#include <iostream>
using namespace std;
struct Base
{
virtual void printName()
{
cout << "Base" << endl;
}
};
struct Interface
{
virtual void foo()
{
cout << "Foo function" << endl;
}
};
struct Derived : public Base, public Interface
{
virtual void printName()
{
cout << "Derived" << endl;
}
};
int main(int argc, const char * argv[])
{
Base *b = new Derived();
Interface *i = dynamic_cast<Interface*>(b);
i->foo();
return 0;
}
#包括
使用名称空间std;
结构基
{
虚拟void printName()
{
cout如果dynamic\u cast
成功,则它是有效的。它已在运行时执行类型安全检查。它是有效的代码
为什么?
因为dynamic\u cast
会告诉您所指向的对象实际上是否属于您要强制转换的类型。
在这种情况下,所指向的实际对象是派生的
类型,而派生的
类型的每个对象也是接口的
(因为派生的
继承自接口
)因此,dynamic\u cast
是有效的,它可以工作。只要所涉及的类至少有一个虚拟方法(可以是虚拟析构函数),使用dynamic\u cast
是正确的,并且可以在一致的编译器上工作
与static\u cast
不同,dynamic\u cast
允许运行时检查类型信息。但是,这也意味着它可能会失败,并在使用它来转换指针时返回一个NULL
。如果转换结果可能不成功,则应检查转换结果
在您提出的上一个问题中,这些类没有任何虚拟方法,因此无法工作,因为dynamic\u cast
不能用于此类类。请考虑以下几点:
Base *b = new B();
Interface *i = dynamic_cast<Interface *>( b );
Base*b=新的b();
接口*i=动态_-cast(b);
应该这样做吗?不。为什么?因为Base
和Interface
彼此不相关。但是,在特殊情况下,指向Base
的指针指向同样从Interface
派生的对象时,可以强制转换(阅读:诱使编译器将对象视为接口
)类型的基
指针,并进一步使用动态转换
运算符的结果。您的代码是有效的,因为标准在5.2.7第4段(C++2003标准)中有这样的规定:
运行时检查按如下逻辑执行:
-如果在v指向(引用)的最派生对象中,v指向(引用)T对象的公共基类子对象,并且如果只有一个T类型的对象是从v指向(引用)的子对象派生的,则结果是指向该T对象的指针(左值引用)
-否则,如果v指向(引用)最派生对象的公共基类子对象,并且最派生对象的类型具有类型T的基类,即明确且公共的,则结果是指向最派生对象的T子对象的指针(左值引用)
-否则,运行时检查将失败
请注意在运行时检查中使用“最派生的对象”。在您的示例中,“最派生的对象”对于您的Base*b
对象是一个派生的对象。由于类派生的公开继承自Base
和接口
,在这种特殊情况下,Base*
对象可以转换为接口*
。答案中的注释对于您前面的问题,请务必说明动态\u cast
将在您的案例中起作用。虽然在本例中恰好是这样,但我不想开创“如果它起作用,它就是正确的”的先例因为它是动态的,所以这就是论点。我不想再解释上10多个众所周知的问题SO@UmNyobe:OP的问题是它为什么有效?答案不是因为dynamic\u cast
这么说。他已经知道dynamic\u cast
这么说了(OP展示了一个精心制作的示例代码来演示它)真正的问题是为什么dynamic\u cast
有效?与我前面的问题有什么区别?(真的不明白)@安德鲁:没有区别,埃米利奥·加拉瓦格利亚在上一个问题中给了你同样的答案。@安德鲁:dynamic\u cast
只有在类(也称多态类)中至少有一个virtual
方法时才有效。请参阅。您之前的示例没有任何virtual
方法,因此无法使用dynamic\u-cast
。我是否理解dynamic\u-cast中涉及的所有类都必须是多态的?安德鲁:是的。如果基类是多态的,则所有派生类也将是多态的。您只需要一个virtual
methodo它甚至可以是一个析构函数。