C++:使用类型信息测试类继承

4
我有一个指向多态类型的指针 p,还有一个在同一继承体系中的类的 type_info ti
如果我只是比较 typeid(*p) == ti,那么我可以在运行时测试指针是否指向该类的直接实例。
是否有类似的方法使用 C++ 的 RTTI 来测试 *p 是否继承自该类?
3个回答

2

在标准C++中无法实现这一点。但是,如果您使用的是具有Itanium C++ ABI1的实现,则可以执行此操作,例如:

#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。

我没有,唉(我甚至没有STL)。我以为这是答案,但是找不到任何明确的陈述。哦,那么就用自定义RTTI吧... - David Given
@DavidGiven - 可能是你的实现具有类似的ABI。 - Flexo

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*转换为Derived*


很不幸,dynamic_cast<>只能在编译时知道类是什么的情况下使用。但我不知道:我只有一个关于该类的 type_info。我实际上不需要转换指针,只需要确定所指向的对象是否继承自我拥有 type_info 的类。 - David Given
@DavidGiven,我误解了你的问题。所以不行,但是你可以创建一个map<typeinfo*,dynamic_cast_wrapper>,让你做想做的事情。如果你有兴趣,告诉我,我会发布详细的答案。 - Frédéric Terrazzoni
没问题,谢谢;我已经有一个自定义RTTI的计划来完成这个任务,但是想先检查一下是否真的需要它。 - David Given
我刚想到,无论如何我的建议都有一部分是错误的。像我建议的那样正确包装dynamic_cast并不容易! - Frédéric Terrazzoni
很久以前就有人问过这个问题了.. 我想知道新的C++标准是否有一些扩展可以涵盖这个问题? - Markus

0

非常感谢Flexo。我已经研究了C++ ABI有一段时间了。经过一个小时的工作,我得到了这个演示:http://pastebin.com/j7DYY5ej。这里是一个检查某些情况下继承的代码。我为这些类型实现了运算符==、!=、<、>、<=、>=。我计划改进这种类型方程的方式,并在我的项目中使用它。 请注意,我在Linux下使用了G++ 4.8。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接