find size of derived class object using base class pointer

前端 未结 4 1221
名媛妹妹
名媛妹妹 2020-12-09 09:32

Is it possible to find the size of a derived class object using a base class pointer, when you don\'t know the derived type.

Thank you.

4条回答
  •  爱一瞬间的悲伤
    2020-12-09 10:06

    Due to lack of reflection in C++, this is not generally possible with arbitrary classes at a whim. There are some workarounds however. You can write a virtual size() method as others have suggested. You can also use the Curiously Recurring Template Pattern, aka inheriting from Register as well but I wouldn't recommend it, vtable costs 4 bytes per object, subclasses of T report incorrect size and correcting it results in multiple inheritance.

    The best way would be to use a class to register, store and query dynamic size information, without modifying the class you want to query:

    EDIT: As it turns out, due to the inconsistent semantics of typeid, it still needs classes with vtables, see the comments.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    class ClassNotFoundException
    : public exception
    {};
    
    class Register
    {
    
        public:
    
            template 
            static void reg (T* = NULL)
            {
                //  could add other qualifiers
                v[&typeid(T)] = sizeof(T);
                v[&typeid(const T)] = sizeof(T);
                v[&typeid(T*)] = sizeof(T);
                v[&typeid(const T*)] = sizeof(T);
            }
    
            template 
            static int getSize (const T& x)
            {
                const type_info* id = &typeid(x);
                if( v.find(id) == v.end() ){
                    throw ClassNotFoundException();
                }
                return v[id];
            }
    
            template 
            static int getSize (T* x)
            {
                return getSize(*x);
            }
    
            template 
            static int getSize (const T* x)
            {
                return getSize(*x);
            }
    
        protected:
    
            static map v;
    
    };
    
    map Register::v;
    
    class A
    {
        public:
            A () : x () {}
            virtual ~A () {}
        protected:
            int x;
    };
    
    class B
    : public A
    {
        public:
            B() : y () {}
            virtual ~B () {}
        protected:
            int y;
    };
    
    int main ()
    {
        Register::reg();
        Register::reg();
    
        A* a = new B();
        const A* b = new B();
    
        cout << Register::getSize(a) << endl;
        cout << Register::getSize(b) << endl;
    }
    

提交回复
热议问题