我有一个指向多态类型的指针p
。对于同一层次结构中的某个类type_info
,我也有一个ti
。
如果我只是比较typeid(*p) == ti
,那么我可以在运行时测试指针是否指向该类的直接实例。
是否有类似的方法使用C ++的RTTI来测试*p
是否从该类继承?
答案 0 :(得分:2)
单独使用标准C ++无法做到这一点。如果您正在使用具有Itanium C++ ABI 1 的实现,则可以执行此操作,例如:
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>
class base {
protected:
base() {
}
public:
static bool check(const std::type_info& p) {
// Find the real type_info for single inheritance non virtual
const __cxxabiv1::__si_class_type_info* test = dynamic_cast<const __cxxabiv1::__si_class_type_info*>(&p);
return test ? typeid(base) == *test->__base_type : false;
}
virtual ~base() {}
};
class der : public base {
};
class foo {};
int main() {
der d;
foo f;
std::cout << base::check(typeid(d)) << "\n";
std::cout << base::check(typeid(f)) << "\n";
}
这样可行,因为该类型具有单个非虚拟继承的基础。您可以谨慎地支持更多案例dynamic_casts
。
虽然在这些情况下这是可能的,但我认为你正在解决错误的问题 - 基于std::map
的解决方案更具可移植性,并且避免依赖这样的实现细节。
1 令人困惑地命名,它是一个令人惊讶的大型编译器/架构列表,而不仅仅是Itanium
答案 1 :(得分:1)
是的,您可以将dynamic_cast<>
用于此目的。如果您尝试强制转换为Base*
,它会执行运行时检查,以查看您的类是否真的来自Base
(或直接是Base)。如果失败,dynamic_cast<>
会返回nullptr
。示例:
struct Base {
virtual ~Base() {}
};
struct AnotherBase {
virtual ~Base() {}
};
struct Derived : Base {};
Base * basePtr = new Base();
Base * derivedPtr = new Derived();
AnotherBase * anotherBasePtr = new Base();
// is derivedPtr a pointer to a class derived from AnotherBase ?
AnotherBase* test2 = dynamic_cast<AnotherBase*>(derivedPtr); // test2 == nullptr
// is basePtr a pointer to a class derived from Derived ?
Derived * test3 = dynamic_cast<Derived*>(basePtr); // test3 == nullptr
侧节点:
如果dynamic_cast<>
用于转换指针,则会返回nullptr
或转换后的指针。
但是当dynamic_cast<>
用于转换引用时,如果失败,则会引发异常。
dynamic_cast<>
的运行时检查仅适用于多态类型。如果您的Base不包含任何虚函数(=非多态),则无法将Base*
安全地转换为Derived*
。
答案 2 :(得分:0)
非常感谢Flexo。我一直在研究C ++ ABI。经过一个小时的工作,我得到了这个演示:http://pastebin.com/j7DYY5ej。这是在某些情况下检查继承的代码。我为类型实现了运算符==,!=,&lt;,&gt;,&lt; =,&gt; =。我打算改进这种类型方程式并在我的项目中使用它。 请注意,我在Linux下使用了G ++ 4.8。