Search code examples
c++virtual

Trouble with understanding virtual and non-virtual function calls


I have some understanding issues with following code segment and the output. Can anybody provide an explanation mainly why test() works the way as seen in output. I am using MSCV 2008 C++ Compiler.

class AS
{
    int a;

public:
    AS():a(1){show();}
    virtual void show() {cout<<a<<endl;}
    void test() { cout<<"Calling show()"<<endl; this->show();}
};

class BS: virtual public AS
{
    int b;
public:
    BS():b(2){show();}
    virtual void show() {cout<<b<<endl;}
    void test() { cout<<"Calling show()"<<endl; this->show();}
};

class CS:public virtual  AS
{
    int c;
public:
    CS():c(3){show();}
    virtual void show() {cout<<c<<endl;}
    void test() { cout<<"Calling show()"<<endl; this->show();}
};

class DS:BS, public CS
{
    int d;
public:
DS():d(4){show();}
    virtual void show() {cout<<d<<endl;}
    void test() { cout<<"Calling show()"<<endl; this->show();}
};

int main()
{
cout<<"Class Sizes:"<<endl;
cout<<sizeof(AS)<<endl;
cout<<sizeof(BS)<<endl;
cout<<sizeof(CS)<<endl;
cout<<sizeof(DS)<<endl;

AS* aa = new DS();  
aa->test();
aa->show();

delete aa;

return 0;
}

Output is:-

Class Sizes:
8
20
20
32
1
2
3
4
Calling show()
4
4

and an breakpoint exception on deleting aa; Why ?


Solution

  • Here is my bit, pls correct me if I'm wrong.

    [Note: vptr-vtable mechanism is used to implement virtual function calls and vbptr (virtual base class pointer) is used to implement virtual base class. Also, the sizeOf(of some polymorphic class) may vary based on compiler + platform being used]

    1) An instance of class AS would need 8 bytes (4 bytes for "int a" + 4 bytes for hidden vptr) = 8

    2) An instance of class BS would need 20 bytes

    (4 bytes to hold base class AS + 4 bytes padding + 4 bytes for "int b" + 4 bytes for hidden vptr + 4 bytes for vbptr) = 20

    3) An instance of class CS would need 20 bytes

    (4 bytes to hold base class AS + 4 bytes padding + 4 bytes for "int c" + 4 bytes for hidden vptr + 4 bytes for vbptr) = 20

    4) An instance of class DS would need 32 bytes

    (4 bytes to hold shared base class AS + 4 bytes for "int d" + 8 bytes to hold base class BS (accounting for member size + vbptr size)+ 8 bytes to hold base class CS (accounting for member size + vbptr size) + 4 bytes for hidden DS::vptr + 4 bytes for DS::vbptr) = 32

    [Pls note, while implementing vptr-vtable mechanism, the compiler augments vtable with virtual function addresses, there exists a single v-table and a single v-ptr inside the memory model of class DS. Whereas, vbptr would be duplicated inside every virtual base class and inside classes inheriting from them].

    Again, all these are compiler specific implementation and may vary across compilers.

    Also, define all base class destructors as virtual to get rid of crash.