首页 > 编程语言 > 详细

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

时间:2016-04-14 22:37:33      阅读:327      评论:0      收藏:0      [点我收藏+]

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
{
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相同。

技术分享

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

技术分享

 

本文出自 “Sean” 博客,请务必保留此出处http://seann.blog.51cto.com/11126490/1763941

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

原文:http://seann.blog.51cto.com/11126490/1763941

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!