首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 繼承與多態底層原理(上):繼承類型、構造析構順序、虛函數表與動態綁定機制

     編輯:關於C++

三種繼承方式的訪問權限變換

基類成員public 繼承protected 繼承private 繼承
publicpublicprotectedprivate
protectedprotectedprotectedprivate
private不可見不可見不可見

鐵律:只有 public 繼承保持「is-a」關係,protected/private 繼承屬於「implemented-in-terms-of」(組合語義),極少使用。

派生類默認成員函數(六大默認)

  1. 默認構造函數
  2. 拷貝構造函數
  3. 移動構造函數 (C++11)
  4. 拷貝賦值運算符
  5. 移動賦值運算符 (C++11)
  6. 析構函數

編譯器僅在被使用時隱式生成。基類無默認構造 → 派生類必須顯式調用基類構造函數。

構造/析構調用順序鐵律

// 構造順序:
// 1. 虛基類(由最派生類調用)
// 2. 非虛基類(按繼承列表順序)
// 3. 成員對象(按聲明順序)
// 4. 派生類自身構造函數體

// 析構順序:完全相反
// 1. 派生類析構函數體
// 2. 成員對象(逆序)
// 3. 非虛基類(逆序)
// 4. 虛基類(逆序)

賦值兼容規則(public 繼承專屬)

  • ✅ 子類對象 → 父類對象(切片)
  • ❌ 父類對象 → 子類對象
  • ✅ 父類指針/引用 → 子類對象(多態基石)
  • ❌ 子類指針/引用 → 父類對象(需 dynamic_cast 且有風險)

虛函數與動態綁定底層機制

虛表 (vtable) 結構

  • 每個含虛函數的類,編譯器生成一張只讀虛函數地址表。
  • 表項按虛函數聲明順序排列,以 nullptr 結尾。
  • 對象首部隱藏 vptr 指向所屬類的虛表。

構造函數中虛函數行為

class Base {
public:
    Base() { foo(); }  // 呼叫 Base::foo()
    virtual void foo() { cout << "Base"; }
};
class Derived : public Base {
public:
    Derived() { foo(); } // 呼叫 Derived::foo()
    void foo() override { cout << "Derived"; }
};

原因:基類構造期間,vptr 指向 Base 虛表;派生類構造時,vptr 更新指向 Derived 虛表。構造/析構中虛函數調用靜態綁定,不發生多態。

不能聲明為 virtual 的函數

函數類型原因
構造函數對象未完全構建,vptr 尚未初始化完成
拷貝構造同構造函數
靜態成員函數無 this 指針,無法訪問 vptr
友元函數非類成員,無 this

析構函數必須 virtual(基類含虛函數時),否則 delete basePtr 僅調用基類析構 → 內存洩漏/資源未釋放。

純虛函數與抽象類

class Interface {
public:
    virtual void doIt() = 0;  // 純虛函數
    virtual ~Interface() {}   // 虛析構
};
// Interface 不可實例化;子類必須實現 doIt() 才能實例化。

友元與繼承、靜態成員繼承

  • 友元不繼承、不雙向、不傳遞。
  • 基類 static 成員在整個繼承體系中僅一份實例,所有派生類共享。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved