【问题标题】:C++: using typeinfo to test class inheritanceC++:使用 typeinfo 测试类继承
【发布时间】:2017-12-14 15:59:43
【问题描述】:

我有一个指向多态类型p 的指针。我还有一个 type_info 用于同一层次结构中的某个类,ti

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

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

【问题讨论】:

    标签: c++ rtti


    【解决方案1】:

    仅在标准 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 名称混淆,它是一个惊人的大编译器/架构列表,而不仅仅是安腾

    【讨论】:

    • 我没有,唉。 (我什至没有 STL。)我认为这就是答案,但找不到任何明确的陈述。哦,好吧,那就是自定义 RTTI,然后……
    • @DavidGiven - 您的实现可能有类似的 ABI。
    【解决方案2】:

    是的,您可以为此目的使用dynamic_cast&lt;&gt;。如果您尝试强制转换为Base*,它会执行运行时检查以查看您的类是否真的派生自Base(或直接是Base)。如果失败,dynamic_cast&lt;&gt; 返回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&lt;&gt; 转换指针,则返回nullptr 或转换后的指针。

    • BUTdynamic_cast&lt;&gt; 用于转换引用时,它会在失败的情况下引发异常

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

    【讨论】:

    • 不幸的是,dynamic_cast&lt;&gt; 只有在我知道类在编译时时才有效。我不知道:我所拥有的只是班级的type_info。我实际上不需要强制转换指针,只需确定所指向的对象是否继承自我拥有type_info 的类。
    • @DavidGiven 我误解了你的问题。所以不,你不能。但是你可以创建一个 map 让你做你想做的事。如果您有兴趣,请告诉我,我会发布详细答案。
    • 没关系,谢谢;我已经有一个自定义 RTTI 的计划来执行此操作,但想先检查一下我是否真的需要它。
    • 我只是发现我的建议有一部分是错误的。像我建议的那样正确包装 dynamic_cast 并不容易!
    • 很久以前有人问过这个问题。我很感兴趣新的 C++ 标准是否有一些扩展可以涵盖这个问题?
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多