C++: using typeinfo to test class inheritance

后端 未结 3 1832
一生所求
一生所求 2020-12-18 10:03

I have a pointer to a polymorphic type, p. I also have a type_info for a class somewhere in the same hierarchy, ti.

If I just

相关标签:
3条回答
  • 2020-12-18 10:08

    Great thanks to Flexo. I have been researching the C++ ABI for a quite while. After a hour of work, I've got this demo: http://pastebin.com/j7DYY5ej. Here is a code to check inheritance in some cases. I've implemented operators ==, !=, <, >, <=, >= for the types. I'm planning to improve this way of type equation and to use it in my project. Note that I used G++ 4.8 under Linux.

    0 讨论(0)
  • 2020-12-18 10:22

    There's no way to do this in standard C++ alone. If you're using an implementation that has the Itanium C++ ABI1 you can do this though, for example:

    #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";
    }
    

    Here this works because the type has a single, non-virtuallly inherited base. You can support more cases though with care and similar dynamic_casts.

    Whilst this is possible under these certain circumstances I think you're solving the wrong problem though - a solution based around a std::map is more portable and avoids relying on implementation details like this.

    1 confusingly named, it's a surprisingly large compiler/architecture list, not just Itanium

    0 讨论(0)
  • 2020-12-18 10:32

    Yes, you can use dynamic_cast<> for that purpose. If you try to cast to Base*, it performs a runtime check to see if your class really is derived from Base (or directly is a Base). In case of failure, dynamic_cast<> returns nullptr. Example :

    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
    

    Side nodes :

    • if dynamic_cast<> is used to convert pointers, it returns either nullptr or the converted pointer.

    • BUT when dynamic_cast<> is used to convert references it throws an exception in case of failure.

    • The runtime check of dynamic_cast<> is only possible for polymorphic types. If your Base doesn't contain any virtual function (= non polymorphic), it won't be possible to safely convert a Base* to a Derived*.

    0 讨论(0)
提交回复
热议问题