4

我有一个指向多态类型的指针,p. 我在同一层次结构中的某个地方也有type_info一个类,ti.

如果我只是比较typeid(*p) == ti,那么我可以在运行时测试指针是否指向该类的直接实例。

是否有类似的方法可以使用 C++ 的 RTTI 来测试是否*p 继承自该类?

4

3 回答 3

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

虽然在这些特定情况下这是可能的,但我认为您正在解决错误的问题 - 基于 a 的解决方案std::map更具可移植性,并且避免依赖这样的实现细节。

1令人困惑的名称,它是一个惊人的大编译器/架构列表,而不仅仅是安腾

于 2012-07-15T11:50:24.367 回答
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

侧节点:

  • ifdynamic_cast<>用于转换指针,它返回或nullptr或转换后的指针。

  • 但是dynamic_cast<>用于转换引用时,它会在失败的情况下引发异常

  • 的运行时检查dynamic_cast<>仅适用于多态类型。如果您的 Base 不包含任何虚函数(= 非多态),则无法安全地将 a 转换Base*为 a Derived*

于 2012-07-15T10:51:28.350 回答
0

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

于 2012-07-27T19:54:24.317 回答