Home > Blockchain >  how to use sizeof with a variable of a derived class?
how to use sizeof with a variable of a derived class?

Time:01-19

I am trying to get the size of a derived class, but I can't...

class one_t {
    size_t getsizeof() { return sizeof(*this); }     
    ... other members ... 
};

class two_t : public one_t {
    ... supplemental members ...
};
    
void main()
{
    two_t _2;
    
    ::cout << _2.getsizeof(); 
}

The output is always 8!

CodePudding user response:

C doesn't work the way you are attempting.

Even though you are calling getsizeof() on a two_t object, the implicit this pointer that is inside of one_t::getsizeof() is a one_t* pointer, which you are dereferencing, so you end up passing a one_t& reference to sizeof(). It doesn't know this is really pointing at a two_t object, it can only return the size of whatever you actually give it, which in this case is the size of one_t.

To accomplish what you want, you can make getsizeof() be virtual in one_t and override it in two_t, eg:

class one_t {
public:
    virtual size_t getsizeof() const { return sizeof(*this); }
    ... other members ... 
};

class two_t : public one_t {
public:
    size_t getsizeof() const override { return sizeof(*this); }
    ... supplemental members ...
};
    
void main()
{
    one_t _1;
    std::cout << _1.getsizeof(); // returns sizeof(one_t)

    two_t _2;
    std::cout << _2.getsizeof(); // returns sizeof(two_t)
}

Alternatively, you can use Curiously Recurring Template Pattern (provided you never make instances of one_t directly), eg:

template<typename Derived>
class one_t {
public:
    size_t getsizeof() const { return sizeof(Derived); }
    ... other members ... 
};

class two_t : public one_t<two_t> {
public:
    ... supplemental members ...
};
    
void main()
{
    // one_t<> _2; // illegal
    // std::cout << _2.getsizeof(); 

    two_t _2;    
    std::cout << _2.getsizeof(); // returns sizeof(two_t)
}

Alternatively, in C 23 and later, you can use Deducing this instead of CRTP, eg:

class one_t {
public:
    template<class Self>
    size_t getsizeof(this const Self& self) const { return sizeof(self); }
    ... other members ... 
};

class two_t : public one_t {
public:
    ... supplemental members ...
};
    
void main()
{
    one_t _1;
    std::cout << _1.getsizeof(); // Self is deduced as one_t

    two_t _2;
    std::cout << _2.getsizeof(); // Self is deduced as two_t
}

CodePudding user response:

For starters according to the C Standard the function main shall have the return type int

int main()

You need to declare the function as virtual. For example

#include <iostream>

int main()
{
    class one_t 
    {
    public:
        virtual ~one_t() = default;
        virtual size_t getsizeof() const { return sizeof( *this ); }
        int x;
    };

    class two_t : public one_t 
    {
    public:
        size_t getsizeof() const override { return sizeof( *this ); }

        int y;
    };

    std::cout << one_t().getsizeof() << '\n';
    std::cout << two_t().getsizeof() << '\n';
}

The program output might look like

8
12
  • Related