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

C++ 面向物件程式設計入門:建構函式與解構函式完整指南

     編輯:關於C++

一、建構函式

建構函式是類別的特殊成員函式,名稱與類別相同、無回傳型別,在物件建立時自動呼叫,用於初始化成員變數。

核心規則

  1. 每個類別必須有建構函式;若未自行定義,編譯器提供預設建構函式(無參數、不做任何初始化)。
  2. 一旦定義任一建構函式,編譯器不再產生預設建構函式。
  3. 靜態/全域物件以零位元模式初始化;區域物件若無建構函式則值不定。

無參數建構函式範例

class Student {
public:
    Student() { number = 1; score = 100; } // 自動初始化
    void show() { cout << number << endl << score << endl; }
protected:
    int number, score;
};
int main() { Student a; a.show(); } // 輸出 1, 100

帶參數建構函式與多載

class Teacher {
public:
    Teacher(const char* input_name) {
        name = new char[10];
        strcpy(name, input_name); // 深層複製,避免指標指向堆疊
    }
    Teacher() {} // 若需無參數建構,必須額外定義(多載)
    void show() { cout << name << endl; }
    ~Teacher() { delete[] name; } // 釋放動態記憶體
protected:
    char* name;
};
int main() {
    Teacher a("test"); // 呼叫帶參數建構函式
    // Teacher b;     // 錯誤:無無參數建構函式
    a.show();
}

關鍵點: name = input_name; 僅複製指標值,導致解構時 delete 錯誤記憶體區塊,必須配置堆疊空間並 strcpy。

成員物件的自動初始化

若類別成員為另一類別物件,建構外層物件時會自動呼叫成員物件的建構函式。

class Teacher { // 內層類別
public:
    Teacher() { director = new char[10]; strcpy(director, "王大力"); }
    ~Teacher() { delete[] director; }
    char* show() { return director; }
protected:
    char* director;
};

class Student { // 外層類別
public:
    Student() { number = 1; score = 100; }
    void show() { cout << teacher.show() << endl << number << endl << score << endl; }
protected:
    int number, score;
    Teacher teacher; // 成員物件
};
int main() {
    Student a; a.show(); // 自動呼叫 Teacher()
    Student b[5];      // 陣列每個元素皆自動呼叫 Teacher()
}

二、解構函式

解構函式名稱為 ~類別名(),無參數、無回傳值、不可多載,在物件生命週期結束時自動呼叫,用於釋放資源(動態記憶體、檔案控制代碼、Socket 等)。

防止記憶體洩漏

class Teacher {
public:
    Teacher() { director = new char[10]; strcpy(director, "王大力"); }
    ~Teacher() { cout << "釋放堆疊 director 1 次"; delete[] director; cin.get(); }
    char* show() { return director; }
protected:
    char* director;
};
// 執行時會在 main 結束前印出 6 次釋放訊息(1 個 a + 5 個 b[5])

三、成員初始化清單

若成員物件只有帶參數建構函式,無法在類別定義內直接傳參,必須使用初始化清單(冒號語法)。

錯誤嘗試

class Student {
    Teacher teacher("王大力"); // 編譯錯誤:類別定義非物件,無法傳參
};

正確寫法:初始化清單

class Student {
public:
    Student(const char* temp) : teacher(temp) { // 冒號後指定呼叫 teacher 的建構函式
        number = 1; score = 100;
    }
protected:
    int number, score;
    Teacher teacher;
};
int main() { Student a("王大力"); a.show(); }

可同時初始化多個成員、const 常數成員、參考成員:

class Student {
public:
    Student(const char* temp, int& pk) : teacher(temp), pk(pk), ps(10) {
        number = 1; score = 100;
    }
protected:
    Teacher teacher;
    int& pk;        // 參考成員
    const int ps;   // 常數成員
    int number, score;
};
int main() {
    char* t_name = "王大力";
    int b = 99;
    Student a(t_name, b); // pk 綁定 b,ps 初始化為 10
}

注意: 初始化清單中 pk(pk) 為參考綁定,非函式呼叫;ps(10) 為常數初始化。C++ 允許 int a(10) 等同 int a = 10,但清單中只能用括號不能用等號。

四、物件建構順序

  1. 全域/靜態物件:在 main() 之前建構;函式內 static 物件僅首次呼叫時建構一次。
  2. 成員建構順序:依類別定義中宣告順序建構,非初始化清單順序。

順序陷阱範例

class Test {
public:
    Test(int j) : pb(j), pa(pb + 5) {} // 看似 pa=15
public:
    int pa; // 先宣告
    int pb; // 後宣告
};
int main() {
    Test a(10);
    cout << a.pa << endl; // 輸出亂碼!因為 pa 先建構,此時 pb 尚未初始化
    cout << a.pb << endl; // 10
}

修正: 調整宣告順序 int pb; int pa;,或在建構函式本體內賦值 pa = pb + 5;。

五、最佳實務建議

  • 永遠為擁有動態資源的類別撰寫解構函式(遵循 RAII)。
  • 善用初始化清單初始化成員物件、常數、參考,效率高於建構函式本體賦值。
  • 若類別需支援複製,請實作複製建構函式與複製指派運算子(或 =delete 禁用),避免淺層複製導致雙重釋放。
  • 建構順序依宣告順序,設計類別時將「被依賴的成員」宣告在前。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved