您好,登錄后才能下訂單哦!
非虛擬繼承
【帶虛函數(shù)的類】
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;
}
Base類沒有顯式定義自己的構造函數(shù),此時編譯器會和成默認的構造函數(shù),
合成的構造函數(shù)中主要完成在對象頭4個字節(jié)中填寫虛表地址:
Base類對象最后的模型如下:
注意:同一個類的對象共用同一個虛表
從上述的結果中可以得到印證。
【單繼承(派生類中沒有虛函數(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類的虛函數(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<<"虛表結束:"<<endl;
}
int main()
{
Base b1;
Derive d1;
return 0;
}
按照如上分析的順序,探索下單繼承下派生類對象模型以及虛表
首先看看編譯器為派生類合成的缺省構造函數(shù):
派生類構造函數(shù)中進行了如下事情:
Derive d1;
d1._data1 = 0x01;
d1._data2 = 0x02;
派生類最后的對象模型為:
【單繼承(派生類中有虛函數(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()
{
cout<<"Derive::FunTest1()"<<endl;
}
virtual void FunTest3()
{
cout<<"Derive::FunTest3()"<<endl;
}
virtual void FunTest4()
{
cout<<"Derive::FunTest4()"<<endl;
}
int _data2;
};
int main()
{
PrintVtable();
return 0;
}
派生類對象模型及虛表建議規(guī)則:
【多繼承(派生類不覆蓋基類虛函數(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;
};
int main()
{
cout<<"sizeof(Derive) = "<<sizeof(Derive)<<endl;
Derive d;
d._data1 = 0x01;
d._data2 = 0x02;
d._data3 = 0x03;
PrintVtable();
return 0;
}
同樣:看看編譯器合成的派生類的對象做了什么工作
觀察下派生類的對象模型和虛表的建立過程
從上面的結果可以看出,Derive類自己特有的虛函數(shù)直接添加在Base類對應虛函數(shù)表最后的位置,大家可將Base和Base1的順序交換驗證下。
【多繼承(派生類覆蓋基類虛函數(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;
};
int main()
{
PrintVtable();
return 0;
}
此時派生類的對象模型和虛表的結構:
虛擬繼承
// 沒有虛函數(shù)覆蓋,但派生類有自己的虛函數(shù)
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;
};
虛擬繼承編譯器為派生類合成的默認構造函數(shù)分析
編譯器為派生類合成的默認構造函數(shù)任務分析:
虛擬繼承派生類對象模型分析
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。