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

虛函數訪問控制與多態行為深度解析

     編輯:C++ 入門

核心結論

虛函數的訪問控制(public/protected/private)僅在編譯期靜態綁定階段生效;運行期多態調用通過虛函數表動態分發,**不受派生類覆蓋函數訪問修飾符限制**。

場景 1:基類 public virtual,派生類 private override

class Base {
public:
    virtual void f(int i = 0) { cout << "Base: " << i << endl; }
};

class Derived : public Base {
private:
    void f(int i = 1) { cout << "Derived: " << i << endl; }
};

int main() {
    Base *b = new Derived();
    b->f(); // 輸出: Derived: 0
}

分析

  1. 編譯期訪問檢查:`b->f()` 中 `b` 靜態類型為 `Base*`,`Base::f` 是 public,通過編譯。默認參數 `i=0` 在編譯期綁定(靜態類型決定)。
  2. 運行期動態分發:`f` 是 virtual,通過 `b` 的動態類型 `Derived` 的 vptr 找到 `Derived::f` 並調用。**此時不再檢查 `Derived::f` 的 private 屬性**。
  3. 默認參數陷阱:輸出 `0` 而非 `1`,因為默認參數是靜態綁定的,隨調用處靜態類型(`Base`)決定。

場景 2:基類 private virtual,派生類 public override

class Base {
private:
    virtual void f() { cout << "Base" << endl; }
};

class Derived : public Base {
public:
    void f() { cout << "Derived" << endl; }
};

int main() {
    Base *b = new Derived();
    // b->f(); // 編譯錯誤:Base::f 是 private,靜態類型 Base* 不可訪問
}

編譯直接失敗,因為靜態類型 `Base*` 看不到 `f`。即使動態類型有 public `f`,也無法調用。

原理總結

  • 訪問控制 = 編譯期靜態綁定規則:根據調用表達式的靜態類型檢查。
  • 多態分發 = 運行期動態綁定機制:根據對象動態類型查虛表調用,不做訪問檢查。
  • 設計建議:虛函數在基類通常聲明為 public 或 protected;派生類覆蓋時保持相同或更寬鬆的訪問級別,避免混淆。私有虛函數僅用於「模板方法模式」中基類內部調用、不希望外部直接調用的場景。

參考資料

C++ FAQ: "Virtual functions and access control" — 訪問控制不影響虛函數覆蓋與動態分發。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved