C++ 在运行时检查对象是否实现接口

c++ checking at runtime if object implements interface

本文关键字:是否 实现 接口 对象 检查 运行时 C++      更新时间:2023-10-16

我前段时间问过这些问题:从基类到不同派生类的多重继承转换

但我仍然不确定我是否理解答案。问题是:下面的代码有效吗?

#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;
}

代码按照我想要的方式工作。但据我了解,根据前面的问题,它不应该。所以我不确定这样的代码是否有效。谢谢!

它是有效的代码。

为什么?
因为dynamic_cast告诉您所指向的对象是否实际上是您要投射到的类型。
在这种情况下,指向的实际对象是 Derived 类型,并且类型Derived的每个对象也是 Interface 类型(因为 Derived 继承自 Interface (,因此dynamic_cast是有效的并且它有效。

只要所涉及的类至少有一个虚拟方法(可以是虚拟析构函数(,按照您的方式使用 dynamic_cast 都是正确的,并且可以在符合要求的编译器上运行。

static_cast不同,dynamic_cast可以允许运行时检查类型信息。 但是,这也意味着它可能会失败,并在使用它来强制转换指针时返回NULL。 应检查转换结果是否有可能不成功。

在你问的上一个问题中,这些类没有任何虚拟方法,因此不起作用,因为dynamic_cast不能在这样的类上使用。

如果dynamic_cast成功,那么它是有效的。它已经在运行时执行类型安全检查。

请考虑以下事项:

Base *b = new B();
Interface *i = dynamic_cast<Interface *>( b );

这应该有效吗?不。为什么,因为BaseInterface彼此没有关系。但是,在指向Base的指针指向一个也派生自Interface对象的特殊情况下,您可以强制转换(阅读:诱使编译器认为该对象为Interface类型(Base指针并进一步使用 dynamic_cast 运算符的结果。

您的代码是有效的,因为标准在 5.2.7 第 4 段(C++ 2003 年标准(中是这样说的:

运行时检查按逻辑执行如下:

— 如果在由 v 指向(引用(的最派生对象中,v 指向(引用(到 T 对象的

公共基类子对象,并且如果只有一个类型 T 的对象派生自指向(引用(由 v 指向(引用(的子对象,则结果是指向该 T 对象的指针(引用的左值(。

— 否则,如果 v 指向(引用(派生最多的对象的公共基类子对象,并且派生最多的对象的

类型具有明确且公共的 T 类型的基类,则结果是一个指针(引用(到派生最多的对象的 T 子对象。

— 否则,运行时检查将失败。

请注意在运行时检查中使用"最派生的对象"。在您的示例中,Base *b对象的"派生最多的对象"是Derived对象。由于类DerivedBaseInterface公开继承,在这种特殊情况下,Base*对象可以强制转换为Interface*