C++里的继承和多态(下)——单继承、多继承、菱形继承(含虚拟函数的继承)

本文详细探讨了C++中的继承和多态,包括单继承、多继承和菱形继承的实现原理。讲解了带有虚函数的类如何在对象模型中体现,以及在不同继承情况下虚表的构造和更新规则。还分析了派生类如何处理基类的虚函数,尤其是在存在覆盖时的行为。
摘要由CSDN通过智能技术生成

1、带有虚函数的类

class Base
{
public:
                 virtual void FunTest1()
                {
                                cout << "Base::FunTest1()" << endl;
                }

                 virtual void FunTest2()
                {
                                cout << "Base::FunTest2()" << endl;
                }

                 int _data1;
};
int main()
{
                 Base b;
                b._data1 = 0x01;
                 return 0;
}

对象模型:


mian函数的反汇编:

如果类中没有自己写构造函数,并且含有虚函数,那么编译器就会合成一个缺省的构造函数。


 

Base()的构造函数分析:

1>在它的构造函数中主要完成的是:在&b指向的那块空间中,填写了虚指针,

2>注意:虚表是编译器在编译和链接完成之后就已经建立好的,在构造函数中只是将虚表的地址填写到对象的前4个字节。

3>虚表中虚函数地址的存放顺序,是按照它在类中声明的顺序存放的。

4>虚表中最后的00 00 00 00 表示虚表结束(编译器不同就不一定了)


vptr指向虚表:


对象模型:

先是虚函数指针,再是该类的数据成员


2、单继承(派生类中没有虚函数的覆盖)

class Base
{
public:
     virtual void FunTest1()
        {cout<<"Base::FunTest1()"<<endl;}
 
     virtual void FunTest2()
        {cout<<"Base::FunTest2()"<<endl;}
     int _data1;
};
class Derive:public Base
{
public:
     virtual void FunTest3()
        {cout<<"Derive::FunTest3()"<<endl;}
 
     virtual void FunTest4()
        {cout<<"Derive::FunTest4()"<<endl;}
     int _data2;
}; 
// 打印虚表
typedef void (*VtbFun)();
void PrintVtable()
{
     cout<<"Derive类的虚函数表: "<<endl;
     Derive d1;
     d1._data1 = 0x01;
     d1._data2 = 0x02;
 
     int* pVTable = (int*)*(int*)&d1;
     VtbFun FunTest = (VtbFun)*pVTable;
     while(NULL != FunTest)
     {
        FunTest();
        cout<<(int*)FunTest<<endl;
        pVTable += 1;
        FunTest = (VtbFun)*pVTable;
     }
     cout<<"虚表结束: "<<endl;
}
int main()
{
     Base b1;
     Derive d1;
     return 0;
}



 

主要还是完成虚指针的填写



在是Derive的构造函数:

派生类最后的对象模型为:如果派生类没有对基类中的虚函数进行重写时,派生类中的虚表先是基类的虚函数地址,然后再加上自己的虚函数地址。虚函数地址的顺序为在类中声明的顺序。



派生类中Base的虚表





3、单继承(含有虚函数的覆盖)

class Base
{
public:
                 virtual void FunTest1()
                {
                                cout << "Base::FunTest1()" << endl;
                }
                 virtual void FunTest2()
                {
                                cout << "Base::FunTest2()" << endl;
                }
                 int _data1;
};
class Derive :public Base
{
public:
                 virtual void FunTest1()//覆盖基类中的FunTest1
                {
                                cout << "Derive::FunTest1()" << endl;
                }
                 virtual void FunTest3()
                {
                                cout << "Derive::FunTest3()" << endl;
                }
                 virtual void FunTest4()
                {
                                cout << "Derive::FunTest4()" << endl;
                }
                 int _data2;
};
typedef void (*VtbFun)();
void PrintVtable()
{
                cout << "Derive类的虚函数表: " << endl;
                 Derive d1;
                d1._data1 = 0x01;
                d1._data2 = 0x02;

                 int* pVTable = (int *)*(int*)&d1;
                 VtbFun FunTest = (VtbFun )*pVTable;
                 while (NULL != FunTest)
                {
                                FunTest();
                                cout << ( int*)FunTest << endl;
                                pVTable += 1;
                                FunTest = ( VtbFun)*pVTable;
                }
                cout << "虚表结束: " << endl;
}
int main()
{
                PrintVtable();
                 return 0;
}



 

派生类对象模型及虚表建立规则:先将基类的虚表搬移过来,若派生类对基类中的某个函数进行了重写,则会用派生类重写的虚函数的地址替换掉虚表中相应位置基类中虚函数的地址,替换完之后再将派生类自己的虚函数地址按照声明的顺序添加到虚表中


4、多继承(没有虚函数的覆盖)

class Base
{
public:
                 virtual void FunTest1()
                {
                                cout << "Base::FunTest1()" << endl;
                }
                 virtual void FunTest2()
                {
                                cout << "Base::FunTest2()" << endl;
                }
                 int _data1;

};

class Base1
{
public:
                 virtual void FunTest3()
                {
                                cout << "Base1::FunTest3()" << endl;
                }
                 virtual void FunTest4()
                {
                                cout << "Base1::FunTest4()" << endl;
                }
                 int _data2;
};

class Derive :public Base, public Base1
{
public:
                 virtual void FunTest5()
                {
                                cout << "Derive::FunTest5()" << endl;
                }
                 int _data3;
};

typedef void (*VtbFun)();
void PrintVtable()
{
                cout << "Derive类的虚函数表: " << endl;
                 Derive d1;
                d1._data1 = 0x01;
                d1._data2 = 0x02;
                 int* pVTable = (int *)*(int*)&d1;
                 VtbFun FunTest = (VtbFun )*pVTable;
                 while (NULL != FunTest)
                {
                                FunTest();
                                cout << ( int*)FunTest << endl;
                                pVTable += 1;
                                FunTest = ( VtbFun)*pVTable;
                }
                cout << "虚表结束. " << endl;
}

int main()
{
                 Derive d;
                d._data1 = 0x01;
                d._data2 = 0x02;
                d._data3 = 0x03;
                PrintVtable();
                 return 0;
}


 

5、多继承(含有虚函数的覆盖)

class Base
{
public:
                 virtual void FunTest1()
                {
                                cout << "Base::FunTest1()" << endl;
                }
                 virtual void FunTest2()
                {
                                cout << "Base::FunTest2()" << endl;
                }
                 int _data1;
};

class Base1
{\ј��	i�	wc���Q��⁡�)#p*�r^��5�*�)����?�)R���88xuz^D�3U_�	�=���`1�9�@��Z`��:��0�=�*��2.0#@��:���tUb4��:��c �b�Y�7J�XJ��|"~u��r �M�b���.��)2pLB}Ug�@S�x82�Q�d;.��[�
4�xuG1��Y2!$gŷ�dI�Hc<�Z�s�ʋ��3��8J!�'$DF�J�•eAU�\�uGʺǥO�S*�`�u0]¦)=@�f�	n
a¡�@�6�����Q�b8�y8�N*0*=4x�cSt�F65G��F���`��R�X|z��2��v4.غ���m��.�#@<`B�(�q���w.�/��H�J�װ��u/9�]KcV��)�/
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值