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

C++ 派生類構造函數:基類初始化機制、參數傳遞與調用順序鐵律

     編輯:C++ 基礎

核心矛盾與解決方案

矛盾:派生類需初始化繼承來的基類成員,但基類 private 成員在派生類不可訪問。
解決:派生類構造函數調用基類構造函數完成基類部分初始化。

語法:初始化列表調用基類構造

class People {
protected: char* m_name; int m_age;
public: People(char* name, int age) : m_name(name), m_age(age) {}
};

class Student : public People {
    float m_score;
public:
    Student(char* name, int age, float score)
        : People(name, age), m_score(score) { }  // 調用基類構造 + 成員初始化
    void display();
};

關鍵點

  • People(name, age) 在初始化列表中調用(函數頭部)
  • 參數為實參:可用派生類參數、常量、區域變量
  • 順序不影響執行順序:基類永遠優先構造

基類構造調用順序鐵律

  1. 單繼承:基類 → 派生類
  2. 多層繼承:A → B → C 順序構造
  3. 多重繼承:按基類聲明順序構造(非初始化列表順序)
  4. 虛繼承:虛基類最優先,再按聲明序

基類構造調用規則:必須調用,否則用預設

情況行為
初始化列表顯式調用 Base(args)調用指定構造函數
未顯式調用自動調用 Base() (預設構造)
無預設構造且未顯式調用編譯錯誤

驗證代碼

class People {
public:
    People() : m_name("xxx"), m_age(0) { cout << "People()" << endl; }
    People(char* name, int age) : m_name(name), m_age(age) { cout << "People(name,age)" << endl; }
protected: char* m_name; int m_age;
};

class Student : public People {
public:
    Student() : m_score(0) { cout << "Student()" << endl; }  // 隱式調用 People()
    Student(char* name, int age, float score) : People(name, age), m_score(score) {
        cout << "Student(name,age,score)" << endl;
    }
    void display();
private: float m_score;
};

int main() {
    Student stu1;           // 輸出: People() → Student()
    Student stu2("小明",16,90.5); // 輸出: People(name,age) → Student(name,age,score)
}

禁止調用間接基類構造

class A { ... };
class B : public A { ... };
class C : public B {
    C() : A(10) { }  // 錯誤!C 只能調用直接基類 B 的構造
};

理由:B 構造時已調用 A,若 C 再調用將導致 A 雙重初始化。

實參靈活性:不限於形式參數

Student(char* name, int age, float score)
    : People("固定名", 18), m_score(score) { }  // 常量實參
Student(char* name, int age, float score)
    : People(local_var, compute_age()), m_score(score) { }  // 區域變量/函數調用

常見錯誤與正確寫法對比

錯誤寫法問題正確寫法
Student(...) { People(name, age); }函數體中調用,視為建立臨時物件,非初始化基類初始化列表 : People(name, age)
忘記調用基類帶參構造隱式調用預設構造,可能非預期行為/編譯錯誤顯式列出 : Base(args)
嘗試調用間接基類編譯錯誤只調用直接基類

現代 C++ 最佳實踐

  1. 成員初始化統一使用初始化列表(C++11 統一初始化語法 {})
  2. 基類若無預設構造,派生類必須顯式調用帶參構造
  3. 考慮委託構造 (C++11) 減少重複:Student() : Student("default", 0, 0) {}
  4. 繼承建構函數 (C++11) using Base::Base; 直接繼承基類構造簽名

總結

派生類構造函數通過初始化列表調用直接基類構造完成基類部分初始化。核心鐵律:基類優先構造、按聲明順序、只能調用直接基類、未顯式則用預設構造。掌握這些機制,配合現代 C++ 委託/繼承構造特性,能編寫高效、正確、可維護的物件初始化代碼。

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