c++繼承全講解


一、C++中的對象模型

1、 概念

語言中直接支持面向對象程序設計的部分;

對於各種支持的底層實現機制。(沒看懂……)

2、 類中的成員分類

a) 成員函數

  i. static function

  ii. non static function

  iii. virtual function

b)  數據成員

  i. static member data

  ii. non static member data

3、 C++對象模型

a) 類對象內存布局中的包括

  i. non static member data

  ii. vptr(虛函數表指針)

  iii. vbptr(虛基類表指針)

b) 不包括

  i. static member data(存儲在靜態存儲區)

  ii. 成員函數(存儲在代碼區)

c) virtual table

簡稱vtbl。存放着指針,這些指針指向該類每一個虛函數。虛表中的函數地址將按聲明時的順序排列。vtbl在類聲明后就形成了,vptr是編譯器生成的。

d) vptr的位置一般放在一個類對象的最前端。

e) 虛基類表

vbptr指向的表,用於存放虛繼承中,虛基類存儲相對於虛基類表指針的偏移量。

二、繼承類型

1、普通繼承(不包含虛函數)

a、單繼承

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    void fun0(){cout << base << endl;}
    int base;
};
class Derive:public Base
{
public:
    Derive (int a = 2):derive(a){}
    void fun1(){cout << base1 << endl;}
    int derive;
};
復制代碼

b、多繼承

復制代碼
class Base1
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2
{
public:
    Base2 (int a = 3):base2(a){}
    void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

c、菱形繼承

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    void fun0(){cout << base << endl;}
    int base;
};
class Base1:public Base
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2:public Base
{
public:
    Base2 (int a = 3):base2(a){}
    void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

 

注:菱形繼承存在二義性問題,編譯都不通過,只能通過指定特定基類的方式進行訪問基類變量。

Derive d;

       d.base =3; // 不正確

       d.Base1::base = 3; // 正確

2、普通繼承(包含虛函數)

  a、單繼承(包含虛函數)

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    virtual void fun0(){cout << base << endl;}
    int base;
};
class Derive:public Base
{
public:
    Derive (int a = 2):derive(a){}
    virtual void fun0(){};
    virtual void fun1(){cout << derive << endl;}
    int derive;
};
復制代碼

注:派生類中新增的虛函數追加到虛函數表后面。

b、多繼承(包含虛函數)

復制代碼
class Base1
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2
{
public:
    Base2 (int a = 3):base2(a){}
    virtual void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    virtual void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

注:派生類中新增的虛函數,追加到第一個基類的虛函數表的后面。

       c、菱形繼承(包含虛函數)

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    virtual void fun0(){cout << base << endl;}
    int base;
};
class Base1:public Base
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2:public Base
{
public:
    Base2 (int a = 3):base2(a){}
    virtual void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    virtual void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

注:分析時,由上到下依次分析。存在二義性問題和內存冗余問題。

 3、虛繼承(不包含虛函數)

新增虛基類指針,指向虛基類表,虛基類表中首項存儲虛基類指針的偏移量,接下來依次存儲虛基類的偏移量(偏移量是相對於虛基類表指針的存儲地址)。

   a、單虛繼承(不包含虛函數)

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual public Base
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};
復制代碼

   b、多虛繼承(不包含虛函數)

復制代碼
class Base1
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2
{
public:
    Base2 (int a = 3):base2(a){}
    void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive:virtual public Base1, virtual public Base2
{
public:
    Derive (int value = 4):derive (value){}
    void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

  c、菱形虛繼承(不包含虛函數)

   第一種形式:

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual Base
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};
class Base2:virtual Base
{
public:
    Base2 (int a = 3):base2(a){}
    void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive:virtual public Base1, virtual public Base2
{
public:
    Derive (int value = 4):derive (value){}
    void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

 

注:分析派生類的內存分布時,也是由上到下分析。虛繼承將基類置於內存末尾,但是置於末尾的順序也有一定的次序。首先Base先放到末尾,然后Base1放到末尾,最后Base2放到末尾。

       第二種形式:

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual public Base
{
public:
    Base1 (int a = 2):base1(a){}
    void fun1(){cout << base1 << endl;}
    int base1;
};

class Base2:virtual public Base
{
public:
    Base2 (int a = 3):base2(a){}
    void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

 

注:分析的原則,從上到下,依次分析。

4、 虛繼承(包含虛函數)

a、單虛繼承(包含虛函數)

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    virtual void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual Base
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};
復制代碼

  與普通的包含虛函數的單繼承相比,派生類擁有自己的虛函數表以及虛函數表指針,而不是與基類共用一個虛函數表。注意虛函數表指針和虛基類表指針的存儲順序。

  b、多虛繼承(包含虛函數)

復制代碼
class Base1
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};

class Base2
{
public:
    Base2 (int a = 3):base2(a){}
    virtual void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive:virtual public Base1, virtual public Base2
{
public:
    Derive (int value = 4):derive (value){}
    virtual void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

c、菱形虛繼承(包含虛函數)

       第一種形式:

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    virtual void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual public Base
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};

class Base2:virtual public Base
{
public:
    Base2 (int a = 3):base2(a){}
    virtual void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive:  public Base1, public Base2
{
public:
    Derive (int value = 4):derive (value){}
    virtual void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

第二種形式:

復制代碼
class Base
{
public:
    Base (int a = 1):base(a){}
    virtual void fun0(){cout << base << endl;}
    int base;
};
class Base1:virtual public Base
{
public:
    Base1 (int a = 2):base1(a){}
    virtual void fun1(){cout << base1 << endl;}
    int base1;
};

class Base2:virtual public Base
{
public:
    Base2 (int a = 3):base2(a){}
    virtual void fun2(){cout << base2 << endl;}
    int base2;
};
class Derive: virtual public Base1,virtual public Base2
{
public:
    Derive (int value = 4):derive (value){}
    virtual void fun3(){cout << derive << endl;}
    int derive;
};
復制代碼

自行腦補C++類對象的內存結構……

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM