C++ 在运行时检查对象是否实现接口
c++ checking at runtime if object implements interface
我前段时间问过这些问题:从基类到不同派生类的多重继承转换
但我仍然不确定我是否理解答案。问题是:下面的代码有效吗?
#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 );
这应该有效吗?不。为什么,因为Base
和Interface
彼此没有关系。但是,在指向Base
的指针指向一个也派生自Interface
对象的特殊情况下,您可以强制转换(阅读:诱使编译器认为该对象为Interface
类型(Base
指针并进一步使用 dynamic_cast
运算符的结果。
您的代码是有效的,因为标准在 5.2.7 第 4 段(C++ 2003 年标准(中是这样说的:
运行时检查按逻辑执行如下:
— 如果在由 v 指向(引用(的最派生对象中,v 指向(引用(到 T 对象的公共基类子对象,并且如果只有一个类型 T 的对象派生自指向(引用(由 v 指向(引用(的子对象,则结果是指向该 T 对象的指针(引用的左值(。
— 否则,如果 v 指向(引用(派生最多的对象的公共基类子对象,并且派生最多的对象的类型具有明确且公共的 T 类型的基类,则结果是一个指针(引用(到派生最多的对象的 T 子对象。
— 否则,运行时检查将失败。
请注意在运行时检查中使用"最派生的对象"。在您的示例中,Base *b
对象的"派生最多的对象"是Derived
对象。由于类Derived
从Base
和Interface
公开继承,在这种特殊情况下,Base*
对象可以强制转换为Interface*
。
- 这个极客对极客的trie实现是否存在内存泄漏问题
- cmath 是否借用了 math.h 的实现
- C++标准是否允许<double>在没有开销的情况下实现 std::可选
- glibcxx STL 在实现 std::valarray::sum() 时是否不正确?
- 它是否定义了哪些算法可以接受可变 lambda 的实现?
- std::bind 是否实现了 std::ref 和 std::cref 来消除函数调用的歧义?
- 是否有可能实现O(N)时间和O(1)空间解决方案,以实现C++中的字符串循环移位
- 共享内存的升压容器是否实现锁定?
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- C 混合蛋白,检查模板类型是否实现了某些混合蛋白
- OmNET++动态检查NED模块是否实现了接口
- 如何检查是否实现了每个声明的类函数
- MOV x86指令是否实现C++11 memory_order_release原子存储
- 如何确定类是否实现!=操作员过载
- C++ 在运行时检查对象是否实现接口
- 测试容器是否实现.at()成员访问/ std::sort兼容的正确方法
- 英特尔TBB concurrent_queue是如何工作的?它是否实现了细粒度的并行性
- 如何正确检查对象是否实现了接口
- 这两个矢量初始化是否实现相同的结果
- 我可以知道一个多态对象是否实现了一个任意的抽象类