资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

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

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;
}

对象模型:

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

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

mian函数的反汇编:

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

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

 

Base()的构造函数分析:

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

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

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

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

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

vptr指向虚表:

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

对象模型:

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

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

 

 

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

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

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

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

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

在是Derive的构造函数:

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

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

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

派生类中Base的虚表

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

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

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

 

 

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;
}

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

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

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
{
public:
                 virtual void FunTest3()
                {
                                cout << "Base1::FunTest3()" << endl;
                }
                 virtual void FunTest4()
                {
                                cout << "Base1::FunTest4()" << endl;
                }
                 int _data2;
};
// 这次将继承列表中 Base和Base1 的位置互换
class Derive :public Base1, public Base
{
public:
                 virtual void FunTest1()
                {
                                cout << "Derive::FunTest1()" << endl;
                }
                 virtual void FunTest3()
                {
                                cout << "Derive::FunTest3()" << endl;
                }
                 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;
                d1._data3 = 0x03;

                 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;
}

  

此时派生类的对象模型和虚表的结构:

  派生类虚表建立过程:先建立和Base1相同的部分,在Derive中对FunTest3进行了重写,所以替换掉虚表中原来的Base1::FunTest3改为了Derive::FunTest3,为了提高访问速度,将自己特有的虚函数加在第一份虚表的后面,建立Base虚表的过程与Base1相同。

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

6、虚拟继承

class Base
{
public :
                 virtual void FunTest1()
                {
                                cout << "Base::FunTest1()" << endl;
                }
                 virtual void FunTest2()
                {
                                cout << "Base::FunTest2()" << endl;
                }
                 int _data1;
};
class Derive : virtual 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()
{
                PrintVtable();
                 return 0;
}

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

 


网页标题:C++里的继承和多态(下)——单继承、多继承、菱形继承(含虚拟函数的继承)
转载来源:http://www.cdkjz.cn/article/geggce.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220