Search code examples
c++classinheritancegcctypeof

Size of derived class in virtual base class function


Consider the following code

class A {
    int x, y;
public:
    A(){}
    virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

class B : public A {
    int a, b, c;
public:
    B(){}
};

int main() {
    A obja;
    B objb;

    obja.PrintSize();
    objb.PrintSize();
}

The intent of "PrintSize()" is to get the size of the current class where we are calling it from. What happens is that this-keyword refers to class A even though we are calling it from B. We don't want this since we need this function to be general for child classes.

We could obviously redefine the function verbatim to every class. The code would become harder to hande since there's so many unnesessary lines. Not to mention that re-writing the function to every class would defeat the purpose of deriving it in the first place.

Here's my temporary fix:

class A {
public:
    virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

class B : public A {
public:
    virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

class C : public A {
public:
    virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

class D : public A {
public:
    virtual void PrintSize(){ cout << sizeof(typeof(*this)) << endl; }
};

Solution

  • You can use the CRTP idiom to do this. https://eli.thegreenplace.net/2011/05/17/the-curiously-recurring-template-pattern-in-c The idea is the parent class is a template, so you can have access to the type of the child class directly in it. With that, you'll be able to remove all "PrintSize" from child class.

    Example :

    template <typename Derived>
    class A {
        int x, y;
    public:
        A() {}
        void PrintSize() { cout << sizeof(Derived) << endl; }
    };
    
    class B : public A<B> {
        int a, b, c;
    public:
        B() {}
    };
    
    class C : public A<C> {
    public:
        C() {}
    };
    
    int main() {
        C objc;
        B objb;
    
        objc.PrintSize();
        objb.PrintSize();
    }
    

    The output is :

    8

    20