溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

發(fā)布時(shí)間:2020-07-25 13:07:35 來(lái)源:網(wǎng)絡(luò) 閱讀:962 作者:夏初丶 欄目:編程語(yǔ)言

1、帶有虛函數(shù)的類(lèi)

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

對(duì)象模型:

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

mian函數(shù)的反匯編:

如果類(lèi)中沒(méi)有自己寫(xiě)構(gòu)造函數(shù),并且含有虛函數(shù),那么編譯器就會(huì)合成一個(gè)缺省的構(gòu)造函數(shù)。

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

 

Base()的構(gòu)造函數(shù)分析:

1>在它的構(gòu)造函數(shù)中主要完成的是:在&b指向的那塊空間中,填寫(xiě)了虛指針,

2>注意:虛表是編譯器在編譯和鏈接完成之后就已經(jīng)建立好的,在構(gòu)造函數(shù)中只是將虛表的地址填寫(xiě)到對(duì)象的前4個(gè)字節(jié)。

3>虛表中虛函數(shù)地址的存放順序,是按照它在類(lèi)中聲明的順序存放的。

4>虛表中最后的00 00 00 00 表示虛表結(jié)束(編譯器不同就不一定了)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

vptr指向虛表:

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

對(duì)象模型:

先是虛函數(shù)指針,再是該類(lèi)的數(shù)據(jù)成員

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

 

 


2、單繼承(派生類(lèi)中沒(méi)有虛函數(shù)的覆蓋)

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類(lèi)的虛函數(shù)表: "<<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<<"虛表結(jié)束: "<<endl;
}
int main()
{
Base b1;
Derive d1;
return 0;
}

主要還是完成虛指針的填寫(xiě)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

在是Derive的構(gòu)造函數(shù):

派生類(lèi)最后的對(duì)象模型為:如果派生類(lèi)沒(méi)有對(duì)基類(lèi)中的虛函數(shù)進(jìn)行重寫(xiě)時(shí),派生類(lèi)中的虛表先是基類(lèi)的虛函數(shù)地址,然后再加上自己的虛函數(shù)地址。虛函數(shù)地址的順序?yàn)樵陬?lèi)中聲明的順序。

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

派生類(lèi)中Base的虛表

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

 

 


3、單繼承(含有虛函數(shù)的覆蓋)

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()//覆蓋基類(lèi)中的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類(lèi)的虛函數(shù)表: " << 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 << "虛表結(jié)束: " << endl;
}
int main()
{
                PrintVtable();
                 return 0;
}

派生類(lèi)對(duì)象模型及虛表建立規(guī)則:先將基類(lèi)的虛表搬移過(guò)來(lái),若派生類(lèi)對(duì)基類(lèi)中的某個(gè)函數(shù)進(jìn)行了重寫(xiě),則會(huì)用派生類(lèi)重寫(xiě)的虛函數(shù)的地址替換掉虛表中相應(yīng)位置基類(lèi)中虛函數(shù)的地址,替換完之后再將派生類(lèi)自己的虛函數(shù)地址按照聲明的順序添加到虛表中

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

4、多繼承(沒(méi)有虛函數(shù)的覆蓋)

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類(lèi)的虛函數(shù)表: " << 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 << "虛表結(jié)束. " << endl;
}
int main()
{
                 Derive d;
                d._data1 = 0x01;
                d._data2 = 0x02;
                d._data3 = 0x03;
                PrintVtable();
                 return 0;
}

5、多繼承(含有虛函數(shù)的覆蓋)

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類(lèi)的虛函數(shù)表: " << 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 << "虛表結(jié)束. " << endl;
}
int main()
{
                PrintVtable();
                 return 0;
}

  

此時(shí)派生類(lèi)的對(duì)象模型和虛表的結(jié)構(gòu):

  派生類(lèi)虛表建立過(guò)程:先建立和Base1相同的部分,在Derive中對(duì)FunTest3進(jìn)行了重寫(xiě),所以替換掉虛表中原來(lái)的Base1::FunTest3改為了Derive::FunTest3,為了提高訪問(wèn)速度,將自己特有的虛函數(shù)加在第一份虛表的后面,建立Base虛表的過(guò)程與Base1相同。

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

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類(lèi)的虛函數(shù)表: " << 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 << "虛表結(jié)束: " << endl;
}
int main()
{
                PrintVtable();
                 return 0;
}

C++里的繼承和多態(tài)(下)——單繼承、多繼承、菱形繼承(含虛擬函數(shù)的繼承)

 

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI