Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to determine the size of virtual base class and derived classes from it?

Tags:

c++

#include <iostream>
using namespace std;

class base1{};
class base2{virtual void show(){}};

class test1{    };
class test2{virtual void show(){}};

class derv1:public virtual base1{};
class derv12:public virtual base2{};

class derv2:public virtual base2, public test1{};
class derv22:public virtual base2, public virtual test1{};
class derv222:public virtual base2, public virtual test2{};

int main()
{
    cout<<"sizeof base1 = "<<sizeof(base1)<<endl;
    cout<<"sizeof base2 = "<<sizeof(base2)<<endl;
    cout<<"sizeof derv1 = "<<sizeof(derv1)<<endl;
    cout<<"sizeof derv12 = "<<sizeof(derv12)<<endl;

    cout<<"sizeof derv2 = "<<sizeof(derv2)<<endl;
    cout<<"sizeof derv22 = "<<sizeof(derv22)<<endl;
    cout<<"sizeof derv222 = "<<sizeof(derv222)<<endl;

}

outputs:

sizeof base1 = 1
sizeof base2 = 4
sizeof derv1 = 4
sizeof derv12 = 8
sizeof derv2 = 8
sizeof derv22 = 8
sizeof derv222 = 12

I understand following outputs:

sizeof base1 : 1 => empty class , size is 1. result is OK.

sizeof base2 : 4 => since class has a virtual function, it adds 
                    a vitual pointer in each object of the class
                    ( 32 bit machine) , so added 4 bytes. Result is OK.

sizeof derv1 : 4 => base1 doesn't have  virtual function but since 
                    derv1 is virtually derived from base1 ,added 4 bytes. 
                    I think that each virtual base class
                    added a  pointer in object so i think Result is OK.     

sizeof derv12: 8 => 4 bytes( from virtual pointer) + 4 bytes
                     (virtual base class ) = 8 bytes. Result is OK.

My confusion starts after the above outputs

sizeof derv2  : 8 => 8 bytes( virtual pointer + virtually base class)
                    from base2 + 1 byte from test1 => 9 bytes and adds 3 padding 
                    bytes gives 12 bytes (should print). 
                     why "sizeof (test1)" is not adding in the output ??

sizeof derv22 : 8 => 8 bytes( virtual pointer + virtually base class)
                    from base2 + 4 byte (virtually base class) 
                    from test1  => 12 bytes (should print)

                    why 4 bytes from  test1 (virtual base class)  is not added 
                    in the output?? In the  size of(derv1 ) also has
                    a virtual base class( base1) and out put is 4 bytes means
                    they added 4 bytes in the output. 

sizeof derv222: 12 => 12 bytes( virtual pointer + virtually derived)
                      from base2 + 8 byte( virtual pointer + virtually derived)
                      from test2  => 16 bytes (should print)

Am I missing somethineg or these sizes are system dependent or any thing else??

like image 713
Alok Avatar asked Jun 27 '11 18:06

Alok


People also ask

What is the size of derived class?

If compiled with the Microsoft C++ compiler, the size of DerivedClass is 16 bytes. If compiled with gcc (either c++ or g++), size of DerivedClass is 12 bytes.

What is the size of virtual class?

If an empty class contain virtual function, even though there is no data members in the class, its size will not be 1 byte but 4 byte because of virtual pointer i.e. VPTR. Virtual pointer size on 32 bit platform is 4 bytes and on 64 bit it is 8 bytes.

How do you identify a base class and a derived class?

The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.


1 Answers

The reason that sizeof(base1) and sizeof(test1) are 1 is solely to prevent a most-derived object from having size 0. That's all the standard forbids. Base class sub-objects are allowed to have size 0 (that is, allowed to occupy no bytes), and hence adding base1 as a base doesn't necessarily have to add anything to the size of the class.

The optimization your compiler has made, not allocating any bytes for a base-class sub-object whose type is an empty class, is called the "empty base class optimization". It's not required by the standard that the implementation apply it, but an implementation that didn't might not be considered fit for serious work.

I think derv22 is somewhat similar - if the compiler is capable of dealing with two virtual base classes using a single extra pointer, then it's entitled to do so. Hence, you might only have to "pay" once, rather then "paying" per virtual base. That could depend on the compiler and on the exact relationships between the classes, though, I've never surveyed different implementations to see if and when they're forced to add multiple pointers worth of overhead.

Apparently derv222 has done it, though, at least for your compiler. I suppose that this is because the base2 and test2 base class sub-objects need separate vtable pointers. Probably not that surprising if you consider what happens when you static_cast a derv222* as a pointer to one base or the other - both results need to be capable of having show() called on them, and calling different functions (albeit the show functions currently do nothing). I'm not sure whether it would be possible for another compiler to implement this inheritance in 8 bytes -- for one thing inheritance doesn't have to be implemented using vtables.

like image 187
Steve Jessop Avatar answered Oct 11 '22 12:10

Steve Jessop