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

C++ 繼承存取控制深度解析:public/protected/private 繼承的語意與實戰

     編輯:關於C++

三種繼承方式的核心語意

繼承方式基類 public → 派生類基類 protected → 派生類基類 private → 派生類典型用途
public (IS-A)publicprotected不可訪問介面繼承、多態基類
protectedprotectedprotected不可訪問受控繼承、實現細節隱藏
private (HAS-A / Implemented-in-terms-of)privateprivate不可訪問組合替代、實現繼承

關鐵規則:基類 private 成員在派生類**永遠不可訪問**

無論繼承方式如何,基類 private 成員對派生類**不可見**,只能通過基類 public/protected 介面間接存取。

代碼實證:四種繼承鏈的存取測試

class Base {
public: int pub = 1;
protected: int pro = 2;
private: int pri = 3;
};

// 1. public 繼承:介面保持
class PubDerived : public Base {
    void test() { pub=1; pro=2; /* pri=3 錯誤 */ }
};
class PubUser : public PubDerived {
    void test() { pub=1; pro=2; /* pri=3 錯誤 */ }
};

// 2. protected 繼承:介面降級為 protected
class ProDerived : protected Base {
    void test() { pub=1; pro=2; /* pri=3 錯誤 */ }
};
class ProUser : public ProDerived {
    void test() { pub=1; pro=2; /* pri=3 錯誤 */ }  // 仍可訪問,但屬性為 protected
};

// 3. private 繼承:介面完全封裝
class PriDerived : private Base {
    void test() { pub=1; pro=2; /* pri=3 錯誤 */ }
};
class PriUser : public PriDerived {
    void test() { /* pub=1 錯誤 */ /* pro=2 錯誤 */ /* pri=3 錯誤 */ }  // 全部不可訪問
};

多層繼承的存取權限傳遞機制

Base (pub/pro/pri)
   │
   ├─ public 繼承 → 子類存取級 = 基類存取級
   │                pub→pub, pro→pro, pri→不可訪問
   │
   ├─ protected 繼承 → 子類存取級 = min(基類存取級, protected)
   │                pub→pro, pro→pro, pri→不可訪問
   │
   └─ private 繼承 → 子類存取級 = private
                    pub→pri, pro→pri, pri→不可訪問

實戰選型指南

✅ public 繼承:建模 IS-A 關係 (95%+ 場景)

  • 基類定義**介面契約**,派生類**是**一種基類。
  • 支援多態:基類指標/引用指向派生物件。
  • 外部代碼可通過基類介面使用派生物件。

⚠️ protected 繼承:極少用,僅用於「受控繼承」

  • 希望**進一步派生類**可用基類介面,但**外部代碼不可用**。
  • 實際上「組合 + protected 成員函數」通常更清晰。

🔧 private 繼承:建模 Implemented-in-terms-of (組合替代)

  • 派生類**利用**基類實現功能,但**不對外暴露**基類介面。
  • 需存取基類 protected 成員或重載 virtual 函數時使用。
  • 現代 C++ 傾向用 **組合 (成員變數) + 委託** 替代,除非需利用 using 宣告暴露特定基類成員:
class Widget : private Timer {  // 利用 Timer 實現定時功能
public:
    using Timer::start;  // 選擇性暴露
    using Timer::stop;
    // 外部不可用 Timer::setInterval 等
};

using 宣告精準控制暴露介面

class Base { public: void foo(); protected: void bar(); };
class Derived : private Base {
public:
    using Base::foo;  // 將 private 繼承的 foo 恢復為 public
    // bar 仍為 private
};

常見誤區對比

誤區正確理解
private 繼承隱藏基類所有成員基類 public/protected 成員在派生類內部**可訪問**(但變為 private),僅對外隱藏
protected 繼承比 private 繼承「更開放」對「進一步派生類」較開放,對「外部使用者」同樣隱藏
繼承方式影響物件大小**不影響**,僅影響編譯期存取檢查,無運行期開銷
構造/解構函數受繼承方式影響**不影響**,基類構造函數總是被調用,順序固定

現代 C++ 最佳實踐

  1. 預設用 public 繼承建模介面繼承與多態。
  2. 優先用組合 (成員變數) 代替 private/protected 繼承,耦合度更低、封裝性更好。
  3. 確需 private 繼承時(如需重載 virtual、存取 protected),用 using 精準暴露必要介面。
  4. 基類解構函數必須 virtual (public 繼承時),防止刪除基類指標時派生類資源洩漏。
  5. 用 final (C++11) 禁止進一步繼承,用 override 確保正確重載。

總結

繼承存取控制是**編譯期靜態規則**,核心邏輯:

  1. 基類 private 成員**永遠**對派生類不可見。
  2. public 繼承保持介面層級;protected 降級為 protected;private 全部降級為 private。
  3. 多層繼承中,存取級**只能遞減不能遞增**。
  4. 實戰中:**public 繼承建模 IS-A,組合建模 HAS-A,private 繼承建模 Implemented-in-terms-of (極少用)**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved