Using typeid to get name of derived class

后端 未结 5 1744
孤城傲影
孤城傲影 2021-02-13 21:08

I\'m creating a resource manager that takes in classes derived from the class Resource. My problem is that typeid(..).name() returns the wrong name of the class.

相关标签:
5条回答
  • My problem is that typeid(..).name() returns the wrong name of the class.

    typeid(...).name() is only useful for debugging or logging purposes. As http://en.cppreference.com/w/cpp/types/type_info/name says:

    No guarantees are given, in particular, the returned string can be identical for several types and change between invocations of the same program.

    As for your problem,

    How can I make the first typeid statement yield 'Texture' without using type conversions?

    The safest, easiest and most correct way to do this would be to add a virtual name function of your own to Resource:

    virtual std::string name() const = 0;
    

    Then override it in every subclass to return the name of the class.

    0 讨论(0)
  • 2021-02-13 21:37

    If you are using Qt library, you could use the metaobject to distinguish the resource instances.

    class Resource : public QObject {
        Q_OBJECT
    
    }; // abstract
    
    class Texture : public Resource {
        Q_OBJECT
    };
    
    Resource *texture = new Texture();
    Resource *resource = new Resource();
    
    texture ->metaObject()->className(); // yields 'Texture'
    resource ->metaObject()->className(); // yields 'Resource'
    
    0 讨论(0)
  • 2021-02-13 21:49

    Firstly, typeid can provide dynamic run-time type identification only for values of polymorphic class types. Your classes are not polymorphic. You need at least one virtual method in the base class in order to "activate" the dynamic behavior of typeid.

    Secondly, in order to use typeid for determining the dynamic type of polymorphic object, you have to apply it to the object itself, not to a pointer to the object (as in your code).

    Thirdly, the value returned by name() does not mean much and cannot be used for any practical purposes. Formally, name() can simply return an empty string every time. You have to use (and compare) the type_info objects themselves for run-time type identification.

    0 讨论(0)
  • typeid of a pointer will always be the declared type, because that's the real type of the pointer itself. To know the real type of the object the pointer points to, you need to dereference the pointer to get the actual type: http://ideone.com/FYmp79

    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    struct Resource {
        virtual ~Resource() = default;
    };
    
    struct Texture : Resource {};
    
    int main() {
        Resource *resource = new Resource;
        Resource *texture = new Texture;
    
        cout << typeid(*resource).name() << endl; // yields 'Resource'
        cout << typeid(*texture).name() << endl; // yields 'Texture'
        return 0;
    }
    

    EDIT: as other people said, you need to make the class polymorphic to get the runtime type information.

    0 讨论(0)
  • 2021-02-13 21:53

    The typeid operator can only return the dynamic type of an expression, if that expression is a glvalue to an object of a polymorphic class.

    A class is polymorphic if it defines at least one virtual member function, directly or in one of its bases.

    Since your Resource class and the derived classes don't satisfy this requirement, the typeid operator can only access the static type.

    To solve that, and issues that you will run into as soon as you try to delete a pointer to such a resource, make the destructor virtual.

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