While learning or developing any C++ application you must have
used the Multiple-inheritance feature provided by language. Lot
has been written about it in many places how it do it, how it works and
what is what in multiple inheritance.
There is a very basic thing with respect to multiple inheritance what will
be the size of object ?
Consider following hierarchy.
#include<iostream>
using namespace std;
class Base {
public:
int a;
};
class X:public Base {
public:
int x;
};
class Y:public Base {
public:
int y;
};
class Z:public X,public Y
{ };
int main(){
Z z;
cout <<"size of z = "<< sizeof(z) <<endl;
return 0;
}
Definitely the output will be 16 considering 32 bit int.
Class Name
|
Size in Bytes(32 bit integer)
|
Base
|
4 ( sizeof(a) )
|
X
|
8 ( sizeof(x) + sizeof(Base) )
|
Y
|
8 ( sizeof(y) + sizeof(Base) )
|
Z
|
16 ( sizeof(X) + sizeof(Y) )
|
In virtual base class there will be only single object and all the classes which derives
virtual base class requires a pointer to it so that they can access it.
Consider following hierarchy using virtual inheritance as follow:
#include <iostream>
using namespace std;
class A {
int a;
};
class B : public virtual A {
int b;
} ;
class C : public virtual A {
int c;
};
class D : public virtual B, public virtual C {
int d;
};
class E : public B, public C {
int e;
};
class F : public B, public C{};
class G : public virtual B, public virtual C {};
int main() {
A a;
B b;
C c;
D d;
E e;
F f;
G g;
cout << " size of A" << sizeof(A) << endl;
cout << " size of B" << sizeof(B) << endl;
cout << " size of C" << sizeof(C) << endl;
cout << " size of D" << sizeof(D) << endl;
cout << " size of E" << sizeof(E) << endl;
cout << " size of F" << sizeof(F) << endl;
cout << " size of G" << sizeof(G) << endl;
return 0;
}
Output:
size of A4
size of B12
size of C12
size of D28
size of E24
size of F20
size of G24
Memory Layout:
(gdb) display a
1: a = {a = -6800}
(gdb) display b
2: b = {<A> = {a = 0}, _vptr.B = 0x401188, b = 4196304}
(gdb) display c
3: c = {<A> = {a = 0}, _vptr.C = 0x401168, c = 4197632}
(gdb) display d
4: d = {<B> = {<A> = {a = 0},
_vptr.B = 0x4010c0, b = 6296960},
<C> = {_vptr.C = 0x4010d8, c = 608253861},
_vptr.D = 0x4010a8, d = 0}
(gdb) display e
5: e = {<B> = {<A> = {a = 6298088},
_vptr.B = 0x400ff8, b = 6},
<C> = {_vptr.C = 0x401010, c = 4196224},
e = 0}
(gdb) display f
6: f = {<B> = {<A> = {a = 0},
_vptr.B = 0x400f58, b = 4196998},
<C> = {_vptr.C = 0x400f70, c = 4197725},
<No data fields>}
(gdb) display g
7: g = {<B> = {<A> = {a = 0},
_vptr.B = 0x400ea0, b = 6296960},
<C> = {_vptr.C = 0x400eb8, c = 1},
_vptr.G = 0x400e88}
Here is a memory size table for individual class:
Class Name
|
Size in Bytes(32 bit integer)
|
A
|
4 ( sizeof(A) )
|
B
|
12 (sizeof(A *) + sizeof(vptr.B) + sizeof(int))
|
C
|
12 (sizeof(A *) + sizeof(vptr.C) + sizeof(int))
|
D
|
28 (sizeof(A *) + (sizeof(B *) + sizeof(vptr.B) + sizeof(C *) + sizeof(vptr.C)+ sizeof(vptr.D) + sizeof(int))
|
E
|
24 (sizeof(A *) + (sizeof(B *) + sizeof(vptr.B) + sizeof(C *) + sizeof(vptr.C) + sizeof(int))
|
F
|
20 (sizeof(A *) + (sizeof(B *) + sizeof(vptr.B) + sizeof(C *) + sizeof(vptr.C))
|
G
|
28 (sizeof(A *) + (sizeof(B *) + sizeof(vptr.B) + sizeof(C *) + sizeof(vptr.C)+ sizeof(vptr.D))
|
Above table explains how the size is calculated in Multiple
inheritance.
*** In some compiler size may vary due to padding done by compiler for memory alignment.