c++ 虛繼承詳解
#include <iostream>
using namespace std;
class A
{
virtual void f(){};
};
class B : public virtual A{
virtual void f(){};
};
class C: public virtual A{
virtual void f(){};
virtual void t(){};
};
int main()
{
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
}
此題在vc6.0下結果是 8 12。
回顧一下虛繼承的概念:虛繼承主要解決在多重繼承中的菱形繼承問題,也就是說 B和C類同時繼承了A類,然後D類繼承了B,C類,那麼D類的虛表就會有重複的函式指標,虛繼承就不會了……。實現方法是,在子類中儲存一個父類(虛繼承類)的實體,同時儲存一個指標指向這個實體。指標+實體都是屬於子類,所以sizeof會將兩者也算在內。
cout<<sizeof(B)<<endl; 結果是8原因是 sizeof(A)加上 指向A實體的指標。注意此時沒有屬於B的虛指標。也就是說B沒有自己的虛擬函式。
cout<<sizeof(C)<<endl; C B區別在於C中有一個屬於自己的虛擬函式,所以加上了一個虛指標的大小 所有為12
最後我們來看一個完整的例子以及記憶體結構佈局。圖後有相關程式碼。
有了之前的那個思想,我來講解下 各個結構體的 sizeof();
程式碼如下:
struct A
{
A(int v=100):X(v){};
virtual void foo(void){}
int X;
};
A:很簡單 一個虛表指標 +一個 X 一共是8byte
struct B :virtual public A
{
B(int v=10):Y(v),A(100){};
virtual void fooB(void){}
int Y;
};
B:虛繼承,OK 那就是 sizeof(A)+一個指向虛基類的指標4byte+判斷B中的虛擬函式是不是從A繼承的,如果是則這一部分是0,如果不是則還要再加4byte 存放 虛表 那麼 B一共就是20byte。
struct C : virtual public A
{
C(int v=20):Z(v),A(100){}
virtual void fooC(void){}
int Z;
};
C的分析同A
struct D : public B, public C
{
D(int v =40):B(10),C(20),A(100),L(v){}
virtual void fooD(void){}
int L;
};
D:公共繼承B,C,那麼 直接 sizeof(b)+sizeof(C)+自己的一個虛指標-因為B,C都是虛繼承A,那麼B和C中關於A的指標只要儲存一個,所以要減去4個位元組,那麼D最後一共就是40byte OK
int _tmain(int argc, _TCHAR* argv[])
{
A a;
int *ptr;
ptr = (int*)&a;
cout << ptr << " sizeof = " << sizeof(a) <<endl;
for(int i=0;i<sizeof(A)/sizeof(int);i++)
{
if(ptr[i] < 10000)
{
cout << dec << ptr[i]<<endl;
}
else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;
}
cout << "--------------------------------------" <<endl;
B b;
ptr = (int*)&b;
cout <<"addr:" << ptr << " sizeof = " << sizeof(b) <<endl;
for(int i=0;i<sizeof(B)/sizeof(int);i++)
{
if(ptr[i] < 10000)
{
cout << dec << ptr[i]<<endl;
}
else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;
}
cout << "--------------------------------------" <<endl;
D d;
ptr = (int*)&d;
cout <<"addr:" << ptr << " sizeof = " << sizeof(d) <<endl;
for(int i=0;i<sizeof(D)/sizeof(int);i++)
{
if(ptr[i] < 10000)
{
cout << dec << ptr[i]<<endl;
}
else cout << hex << ptr[i] <<" = " << hex << * ((int*)(ptr[i])) <<endl;
}
return 0;
}
最後一段話很重要:那就是 各個編譯器執行的關於虛繼承的結果不一樣,很簡單,他們處理虛表的機制不一樣,但是有一點可以肯定的是,虛繼承就是為了解決菱形繼承中,B,C都繼承了A,D繼承了B,C,那麼D關於 A的引用只有一次,而不是 普通繼承的 對於A引用了兩次……
所以上面分析的都是浮雲 沒用的東西
相關文章
- C++繼承詳解:共有(public)繼承,私有(private)繼承,保護(protected)繼承C++繼承
- C++虛繼承的概念C++繼承
- 菱形繼承,虛繼承繼承
- C++ 派生類函式過載與虛擬函式繼承詳解C++函式繼承
- 詳解C++中繼承的基本內容C++中繼繼承
- Java 繼承詳解Java繼承
- 虛繼承繼承
- C++ 虛擬函式和虛繼承淺析C++函式繼承
- C++繼承二之虛擬函式C++繼承函式
- C++ 繼承、多型、虛擬函式C++繼承多型函式
- C++中的虛繼承的構造C++繼承
- 三種繼承的方法:public 繼承/private繼承/protected繼承詳解及區別繼承
- JavaScript繼承詳解(二)JavaScript繼承
- JavaScript 繼承方式詳解JavaScript繼承
- C++繼承一之公有繼承C++繼承
- C++繼承C++繼承
- C++知識點隨筆(五):虛繼承C++繼承
- C++ 虛繼承 物件記憶體佈局C++繼承物件記憶體
- C++虛繼承原理與類佈局分析C++繼承
- java繼承基礎詳解Java繼承
- js 組合繼承詳解JS繼承
- Python super繼承詳解Python繼承
- python 多繼承詳解Python繼承
- C++ | 類繼承C++繼承
- C++菱形繼承C++繼承
- C++中公有繼承、保護繼承、私有繼承的區別C++繼承
- C++單繼承、多繼承情況下的虛擬函式表分析C++繼承函式
- C++繼承體系C++繼承
- C++中的繼承C++繼承
- C++繼承三之純虛擬函式pure virtual functionC++繼承函式Function
- 菱形繼承與虛基類繼承
- [C++]繼承和派生類C++繼承
- 說說C++多重繼承C++繼承
- c++ 記憶體 繼承C++記憶體繼承
- C++ 整理15_繼承C++繼承
- C++ protected繼承意義C++繼承
- springmvc中Dispatchservlet繼承體系詳解SpringMVCServlet繼承
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView