1. 程式人生 > 其它 >類相關01

類相關01

類相關01

空類的成員

空類大小為1;

空類的成員:

class foo

{
    ​//空類包含六個成員(所有類的預設成員)
​    //預設認建構函式
    foo();
    //預設拷貝建構函式
    foo(foo &);
    //預設解構函式
    ~foo();
    //預設賦值運算子
    operator=();
    //預設取地址運算子
    operator&();
    //const物件的預設取地址運算子
    const operator&() const;
};

虛繼承

虛繼承與虛擬函式等不同,虛繼承是為了解決菱形繼承的而出現的。
比如我們有父類Human,其中以public方式聲明瞭膚色成員skin;然後我們分別用了兩個子類Asian和European去繼承這個父類,這樣兩個子類也有了自己對應的膚色成員skin以及父類的成員skin,而當我們用新的子類Japanese去同時繼承兩個子類的時候,這時候Japanese就擁有了兩個來自Human的skin成員,便出了問題。
而解決的方案就是虛繼承。在繼承時加上關鍵字virtual,子類物件在繼承時,系統會在一塊連續空間中生成一個虛表(virtual table),子類中儲存指向虛表的虛表指標,虛表中儲存子類相對於虛基類的偏移量,虛繼承的頂層父類的成員在繼承時變為一個虛基類儲存在子類中,在繼承的時候等同於所有虛繼承的子類都從虛基類中繼承了同一個成員,而不是每一次都把自己的父類的成員一起繼承了。

//正常的繼承下成員情況
class Human{
public:
    char skin;
};
//子類
class Asian : public Human
{
     //size 1
public: 
    <base class Human>
        char* A::skin;
};
class European : public Human
{
    //size 1
public:
    <base class Human>
        char* A::skin;
};
//新的子類去繼承前兩個子類,發生菱形繼承
class Japanese : public Asian, public European
{
    //size 2
public:
    //出現二義性
    <base class Asian>
    	<base class Human>
       		char* A::skin;
    <base class European>
    	<base class Human>
        	char* A::skin;
};

//虛繼承方式下的成員
//子類
class Asian : virtual public Human
{
    //size 5
public: 
    //虛表指標
    {vtptr}
    
    (base class Human)
    skin;
};
Asian::$vbtable@:
0 --- |0
1 --- |4 (Asian(Asian+0)Human)

class European : virtual public Human
{
    //size 5
public:
    {vtptr}
    
    (base class Human)
    skin;
};
European::$vbtable@:
0 --- |0
1 --- |4 (European(European+0)Human)
    
class Japanese : virtual public Asian, virtual public European
{
    //size 9
public:
    <base class Aisan>
    {vtptr}
    
    <base class European>
    {vtptr}
    
    (virtual base Human)
    skin;
};

D:: $vbtable@:
0  --- |0 
1  --- |8 <Japanese<Asian+0>Human>;

D:: $vbtable@:
0  --- |0 
1  --- |4 <Japanese<European+0>Human>;

可以通過類間指標來訪問驗證成員:

void *p = &Japanese;
//訪問元素skin
//後半段求偏移量 先用取到子類地址,虛表中的指標步長為int。
((Human*)((char*)p + *(int*)((int*)*(int*)p+1)))->skin;