一、類的定義
1. 類的基本形式
class 類名 {
public: // 公有成員(類內外均可訪問)數據類型 數據成員; // 公有數據成員數據類型 成員函數(參數列表); // 公有成員函數聲明
protected: // 保護成員(類內和派生類可訪問)數據類型 保護數據成員;數據類型 保護成員函數(參數列表);
private: // 私有成員(僅類內可訪問)數據類型 私有數據成員;數據類型 成員函數(參數列表); // 私有成員函數聲明
}; // 類定義結束必須加分號
2. 詳細說明
- 成員分類:類包含兩種成員:
- 數據成員:描述類的屬性,如學生類中的
姓名
、年齡
。 - 成員函數:描述類的行為,如學生類中的
設置年齡
、獲取成績
。
- 數據成員:描述類的屬性,如學生類中的
- 訪問權限:
public
(公有):成員可在類外直接訪問,例如對象名.公有成員
。protected
(保護):成員可在類內和派生類中訪問,類外不可直接訪問。private
(私有):僅類內成員函數或友元可訪問,類外和派生類(除非友元)不可直接訪問。
- 成員函數定義:
- 類內定義:直接在類體中編寫函數體,自動成為內聯函數(隱式
inline
)。 - 類外定義:使用
類名::
作用域限定符,例如:void 類名::成員函數(參數列表) { /* 函數體 */ }
- 類內定義:直接在類體中編寫函數體,自動成為內聯函數(隱式
3. 示例:定義學生類
class Student {
public:// 公有數據成員char name[20]; // 姓名int age; // 年齡// 公有成員函數(類內定義)void set_score(float s) { // 設置成績(私有成員)score = s;}// 公有成員函數(類外定義)float get_score(); // 獲取成績聲明protected:int grade; // 年級(保護成員,派生類可訪問)private:float score; // 成績(私有成員,僅類內訪問)
};// 類外定義成員函數
float Student::get_score() {return score; // 訪問私有成員score
}
二、對象的定義與成員訪問
1. 對象定義
- 語法:
類名 對象名;
?或?類名 對象名(參數列表);
(調用帶參構造函數) - 示例:
Student stu1; // 定義對象stu1(調用默認構造函數) Student stu2("張三", 18); // 假設存在帶參構造函數
2. 成員訪問
- 公有成員:直接通過
對象名.成員名
訪問。stu1.age = 18; // 合法,age是公有成員 strcpy(stu1.name, "李四"); // 合法
- 私有 / 保護成員:通過公有成員函數間接訪問。
stu1.set_score(90.5); // 合法,調用公有函數設置私有成員score // stu1.score = 90.5; // 非法,score是私有成員
三、構造函數:對象的初始化
在面向對象編程中,對象的初始化是一個關鍵環節。構造函數作為類的特殊成員函數,承擔著初始化對象的重要職責。下面將從基礎概念到高級用法逐步解析構造函數的核心知識。
1. 構造函數概述
語法規則
- 函數名:必須與類名完全相同(包括大小寫)。
- 返回值:沒有返回值(不能寫
void
)。 - 調用時機:創建對象時自動調用(棧上定義、堆上
new
操作、函數返回對象等場景)。
核心作用
- 成員初始化:為對象的成員變量賦初始值(如數值類型設為默認值、指針指向有效內存)。
- 資源分配:為對象分配運行所需資源(如動態內存、文件句柄、網絡連接等)。
示例:基礎構造函數
class Book {
public:// 構造函數:初始化書名和頁數Book() {strcpy(title, "未命名"); // 初始化C風格字符串pages = 0;}
private:char title[50];int pages;
};int main() {Book novel; // 創建對象時自動調用Book()構造函數return 0;
}
2. 構造函數分類
(1)無參構造函數(默認構造函數)
定義與特性
- 無參數:函數括號內沒有參數列表。
- 編譯器自動生成:若類中未定義任何構造函數,編譯器會生成一個空的默認構造函數(成員變量初始化為默認值,如數值為 0、指針為
nullptr
)。 - 手動定義的必要性:若定義了其他帶參構造函數,編譯器不再自動生成默認構造函數,需手動定義以支持無參創建對象。
示例:手動定義默認構造函數
class Student {
public:// 顯式定義默認構造函數Student() {id = 0;name = "匿名";score = 0.0f;}
private:int id;std::string name;float score;
};Student stu; // 調用默認構造函數,id=0,name="匿名",score=0.0f
(2)帶參構造函數
定義與作用
- 包含參數:通過參數為成員變量賦初始值,支持靈活初始化。
- 參數作用域:參數名可與成員變量同名,通過
this
指針區分(this->成員變量
)。
示例:通過參數初始化成員
class Circle {
public:// 帶參構造函數:初始化半徑和面積Circle(float r) {radius = r; // 成員變量radius = 參數rarea = 3.14f * r * r; // 計算初始面積}
private:float radius;float area;
};Circle c(5.0f); // 創建半徑5.0的圓,area自動計算為78.5
(3)初始化列表(Constructor Initializer List)
語法與格式
- 位置:在構造函數參數列表后,使用
:
分隔,多個成員用逗號分隔。 - 格式:
構造函數(參數列表) : 成員1(值1), 成員2(值2), ... { 函數體 }
核心優勢
- 效率更高:直接調用成員的構造函數(如類成員對象),避免先默認構造再賦值。
- 必需場景:初始化
const
成員或引用成員(二者必須在定義時初始化)。
示例:初始化列表的使用
class Person {
public:// 普通成員與const成員的初始化Person(std::string n, int a) : name(n), age(a) { // 函數體可空,初始化在列表完成}// 引用成員必須通過初始化列表賦值Person(std::string n, int a, int& ref) : name(n), age(a), ref_num(ref) { }
private:std::string name;int age;const int ref_num; // const引用成員,必須在初始化列表賦值
};// 初始化const成員的錯誤與正確寫法對比
class ErrorDemo {const int value;
public:ErrorDemo() { value = 10; } // 錯誤!const成員不能賦值
};class CorrectDemo {const int value;
public:CorrectDemo() : value(10) { } // 正確!通過初始化列表賦值
};
(4)構造函數重載
重載規則
- 函數名相同,但參數列表不同(參數個數、類型、順序至少有一個不同)。
- 返回值類型無關:不能通過返回值區分重載構造函數。
示例:多種初始化方式
class Vector {
public:// 無參構造:初始化零向量Vector() : x(0), y(0) {}// 單參數構造:二維向量(x=y)Vector(float val) : x(val), y(val) {}// 雙參數構造:指定x和yVector(float x_val, float y_val) : x(x_val), y(y_val) {}
private:float x, y;
};// 調用不同構造函數
Vector v1; // 無參構造,(0, 0)
Vector v2(5.0f); // 單參構造,(5.0, 5.0)
Vector v3(3.0f, 4.0f); // 雙參構造,(3.0, 4.0)
C++14 簡化寫法:= default
- 作用:顯式讓編譯器生成默認構造函數,保持代碼簡潔。
- 示例:
class Simple { public:Simple() = default; // 等價于空的默認構造函數Simple(int x) : data(x) {} private:int data; };
3. 初始化 const 成員的強制要求
為什么必須用初始化列表?
const
成員在聲明后不能被賦值(只能初始化),而構造函數的函數體執行時,成員變量已完成定義,無法再對const
成員賦值。- 初始化列表在成員變量定義時直接賦值,滿足
const
的初始化要求。
示例:const 成員的正確初始化
class MathConstants {
public:// 初始化const成員PI和引用成員epsilon(引用必須初始化)MathConstants(float eps) : PI(3.14159f), epsilon(eps) {}
private:const float PI; // 圓周率,固定值float& epsilon; // 精度引用,必須在初始化列表賦值
};// 錯誤示例:試圖在函數體中賦值const成員
class ErrorCase {const int value;
public:ErrorCase(int v) { value = v; } // 編譯錯誤!const成員不能賦值
};// 正確示例:通過初始化列表賦值
class CorrectCase {const int value;
public:CorrectCase(int v) : value(v) {} // 正確
};
4. 構造函數的最佳實踐
(1)統一使用初始化列表
- 無論是否為
const
成員,優先在初始化列表中賦值,提升效率(尤其對類成員對象)。
(2)避免冗余初始化
- 若成員變量無需特殊處理,可依賴編譯器默認初始化(如
std::string
默認構造為空字符串)。
(3)處理動態資源
- 在構造函數中分配資源(如
new
內存),并在析構函數中釋放(確保資源配對)。class DynamicArray { public:DynamicArray(int size) : data(new int[size]), length(size) {}~DynamicArray() { delete[] data; } // 析構函數釋放內存 private:int* data;int length; };
總結:構造函數核心知識點
特性 | 說明 |
---|---|
必需性 | 創建對象時必須調用構造函數,編譯器自動生成默認構造函數(無其他構造函數時)。 |
初始化方式 | 普通成員可在函數體賦值,const 成員和引用成員必須通過初始化列表初始化。 |
重載規則 | 參數列表不同(個數、類型、順序),支持靈活的對象創建方式。 |
資源管理 | 構造函數分配資源,析構函數釋放資源,確保內存安全。 |
通過合理設計構造函數,開發者能確保對象在創建時處于有效狀態,為后續操作奠定基礎。下一節將深入解析析構函數與對象生命周期管理,進一步理解 C++ 對象的完整生命周期。
四、析構函數:對象的清理
在 C++ 中,對象的生命周期管理至關重要。構造函數負責對象的初始化,而析構函數則承擔著對象銷毀時的清理工作,確保資源正確釋放,避免內存泄漏。下面從基礎概念到實戰應用逐步解析析構函數的核心知識。
1. 析構函數概述
語法規則
- 函數名:以
~
符號開頭,后跟類名(與構造函數對應),例如~ClassName()
。 - 參數與返回值:沒有參數,也沒有返回值(不能寫
void
)。 - 調用時機:
- 棧對象離開作用域時(如函數結束)。
- 堆對象通過
delete
釋放時(如delete p;
)。 - 程序結束時(全局對象和靜態對象銷毀)。
核心作用
- 資源釋放:釋放構造函數或成員函數分配的資源(如動態內存
new
、文件句柄fopen
、網絡連接等)。 - 數據清理:重置成員變量狀態,避免無效引用。
與構造函數的關系
- 配對使用:構造函數分配資源,析構函數釋放資源,形成 “資源管理對”(RAII 模式的基礎)。
- 執行順序:構造函數按 “基類→派生類” 順序執行,析構函數按 “派生類→基類” 逆序執行(確保派生類資源先釋放,基類后釋放)。
2. 示例:釋放動態內存(核心場景)
需求:管理動態數組的生命周期
當類中包含動態分配的內存(如new
創建的數組),必須在析構函數中用delete
釋放,否則會導致內存泄漏。
代碼實現
#include <iostream>
using namespace std;class DynamicArray {
private:int* data; // 動態數組指針int size; // 數組大小public:// 構造函數:分配內存并初始化DynamicArray(int s) : size(s) {data = new int[size]; // 分配size個int的內存空間for (int i = 0; i < size; i++) {data[i] = i; // 初始化數組元素}cout << "構造函數:分配內存,地址=" << data << endl;}// 析構函數:釋放動態內存~DynamicArray() {delete[] data; // 釋放數組內存(與new[]配對)data = nullptr; // 置空指針,避免野指針cout << "析構函數:釋放內存,地址=" << data << endl;}
};int main() {// 棧對象:離開main作用域時自動調用析構函數{DynamicArray arr(5); // 構造函數執行,分配內存} // 作用域結束,析構函數自動調用// 堆對象:顯式調用delete時觸發析構函數DynamicArray* ptr = new DynamicArray(3); // 構造函數執行delete ptr; // 手動釋放,析構函數調用return 0;
}
代碼解釋
-
構造函數:
- 接收參數
size
,使用new[]
分配動態數組內存。 - 初始化數組元素,輸出內存地址以便觀察。
- 接收參數
-
析構函數:
- 使用
delete[]
釋放動態數組(必須與new[]
配對,單個對象用delete
)。 - 釋放后將指針置為
nullptr
,防止后續誤操作(野指針問題)。
- 使用
-
調用場景:
- 棧對象
arr
在離開花括號作用域時,自動調用析構函數。 - 堆對象
ptr
通過delete
顯式釋放,觸發析構函數。
- 棧對象
3. 注意事項與進階知識
(1)默認析構函數:編譯器的 “隱形助手”
- 自動生成條件:若用戶未定義析構函數,編譯器會生成一個默認析構函數(空函數)。
class Simple {int value; // 無自定義析構函數,編譯器生成~Simple() {} };
- 局限性:默認析構函數僅能釋放非動態資源(如基本類型、標準庫對象),對
new
分配的內存、文件句柄等無效,需手動定義析構函數。
(2)析構函數與繼承:順序至關重要
-
基類與派生類的執行順序:
- 創建派生類對象時:先執行基類構造函數 → 再執行派生類構造函數。
- 銷毀派生類對象時:先執行派生類析構函數 → 再執行基類析構函數(與構造順序相反)。
class Base { public:~Base() { cout << "Base析構" << endl; } }; class Derived : public Base { public:~Derived() { cout << "Derived析構" << endl; } };int main() {Derived obj; // 輸出:Base構造 → Derived構造(假設存在構造函數)// 銷毀時輸出:Derived析構 → Base析構return 0; }
(3)析構函數不能重載
- 原因:析構函數沒有參數列表,無法通過參數區分不同版本,因此每個類最多有一個析構函數。
(4)析構函數與異常處理
- 原則:析構函數中避免拋出異常,否則可能導致程序終止。
- 處理方式:若必須處理異常,應在析構函數內部捕獲并處理,而非拋出。
~DynamicArray() {try {delete[] data;} catch (...) {// 處理異常或記錄日志} }
4. 最佳實踐:資源管理的黃金法則
(1)RAII 模式(資源獲取即初始化)
- 核心思想:通過構造函數獲取資源,析構函數釋放資源,確保資源生命周期與對象綁定。
- 典型應用:
- 動態內存:
new
/delete
配對。 - 文件操作:構造函數打開文件,析構函數關閉文件。
class FileHandler { public:FileHandler(const char* path) {file = fopen(path, "r"); // 構造函數打開文件}~FileHandler() {if (file) fclose(file); // 析構函數關閉文件} private:FILE* file; };
- 動態內存:
(2)避免手動管理資源:使用智能指針
- C++11 引入
std::unique_ptr
和std::shared_ptr
,自動管理動態內存,無需手動編寫析構函數。#include <memory> class ModernArray { private:std::unique_ptr<int[]> data; // 智能指針自動釋放內存 public:ModernArray(int size) : data(new int[size]) {} // 無需析構函數 };
總結:析構函數核心知識點
特性 | 說明 |
---|---|
語法特征 | 以~類名 命名,無參數、無返回值,自動調用于對象銷毀時。 |
核心作用 | 釋放動態資源(如new 內存、文件句柄),防止內存泄漏。 |
默認行為 | 未定義時編譯器生成空析構函數,僅適用于無動態資源的類。 |
繼承場景 | 析構順序與構造順序相反(派生類→基類),確保資源正確釋放。 |
最佳實踐 | 結合 RAII 模式,或使用智能指針簡化資源管理,避免手動編寫繁瑣析構邏輯。 |
通過合理設計析構函數,開發者能有效管理對象生命周期,確保程序的穩定性和資源利用率。下一節將深入探討this
指針與靜態成員,進一步理解類的內部機制。
五、this 指針:指向當前對象的 “隱形指針”
1. this 指針作用
- 解決命名沖突:當成員變量與參數同名時,用
this->成員名
區分。class Person { private:char name[20];int age; public:void set_name(char* name) {strcpy(this->name, name); // this->name是成員變量,name是參數} };
2. 隱含參數
- 成員函數隱式包含
this
指針參數,調用時自動傳遞當前對象地址。Person p; p.set_name("Alice"); // 等價于 set_name(&p, "Alice")
3. 返回當前對象引用(鏈式調用)
class Counter {
private:int value;
public:Counter& add(int n) {value += n;return *this; // 返回當前對象引用}
};Counter c;
c.add(10).add(20); // 鏈式調用,等價于 c.add(10); c.add(20);
六、靜態成員:類級別的共享數據與函數
1. 靜態成員變量
-
定義:用
static
修飾,屬于類而非對象,所有對象共享。 -
初始化:必須在類外初始化,格式為
類型 類名::變量名 = 初始值;
。class Student { public:static int total_students; // 聲明靜態成員變量 }; int Student::total_students = 0; // 類外初始化
-
訪問方式:
- 通過類名:
Student::total_students
- 通過對象:
stu1.total_students
(需公有權限)
- 通過類名:
2. 靜態成員函數
- 特點:只能訪問靜態成員(變量 / 函數),無
this
指針。 - 應用場景:統計類的對象數量。
class Student { public:static int get_total() { // 靜態成員函數return total_students;} };
七、const 成員:保護數據不被修改
1. const 成員變量
- 初始化:必須通過構造函數初始化列表賦值,不可修改。
class Math { private:const float PI; // const成員變量 public:Math() : PI(3.14f) {} // 初始化列表賦值 };
2. const 成員函數(常成員函數)
- 語法:在函數聲明后加
const
,保證不修改成員變量。class Circle { private:float radius; public:float get_radius() const { // 常成員函數return radius; // 不可修改radius} };
3. const 對象
- 定義:
const 類名 對象名;
,只能調用常成員函數。const Circle c(5.0); c.get_radius(); // 合法,調用常成員函數 // c.set_radius(6.0); // 非法,set_radius非const函數
八、友元:打破訪問權限的 “特權”
在 C++ 中,類的封裝性通過public/protected/private
嚴格控制成員訪問,但有時需要允許特定的函數或類突破這種限制,直接訪問私有成員。** 友元(Friend)** 機制就是為此設計的 “特權通道”,它允許非類成員函數或其他類的成員函數訪問當前類的私有 / 保護成員。
1. 友元函數
友元函數是獲得類訪問特權的非成員函數,分為兩種類型:全局非成員友元函數和其他類的成員友元函數。
(1)非成員友元函數
定義與聲明
- 作用:允許一個全局函數(不屬于任何類)訪問類的私有 / 保護成員。
- 聲明方式:在類體內用
friend
關鍵字聲明函數原型,格式為:friend 返回值類型 函數名(參數列表);
- 關鍵特性:友元函數不是類的成員,無需通過對象調用,但可訪問類的所有成員。
示例:訪問銀行賬戶余額(私有成員)
#include <iostream>
using namespace std; class BankAccount {
private: float balance; // 私有成員:賬戶余額 public: // 聲明全局函數display_balance為友元 friend void display_balance(const BankAccount& acc); // 構造函數初始化余額 BankAccount(float bal) : balance(bal) {}
}; // 友元函數定義:可直接訪問私有成員balance
void display_balance(const BankAccount& acc) { cout << "賬戶余額:" << acc.balance << " 元" << endl;
} int main() { BankAccount account(10000.5f); display_balance(account); // 合法!友元函數訪問私有成員 return 0;
}
代碼解析
- 友元聲明:
friend void display_balance(...)
在類內聲明,賦予該函數訪問私有成員balance
的權限。 - 參數傳遞:使用
const引用
傳遞對象,避免拷貝構造,提高效率并防止修改原始對象。
(2)其他類的成員友元函數
應用場景
當類 B 的某個成員函數需要訪問類 A 的私有成員時,可將該成員函數聲明為類 A 的友元。
聲明方式
class A {
private: int private_data;
public: // 聲明類B的成員函數B::friend_func為友元 friend void B::friend_func(A& obj);
}; class B {
public: void friend_func(A& obj) { obj.private_data = 100; // 合法!訪問A的私有成員 }
};
示例:類間協作訪問私有成員
#include <iostream>
using namespace std; class Teacher; // 前向聲明,解決類依賴 class Student {
private: int student_id;
public: // 聲明Teacher類的成員函數Teacher::view_id為友元 friend void Teacher::view_id(Student& stu); Student(int id) : student_id(id) {}
}; class Teacher {
public: void view_id(Student& stu) { cout << "學生ID:" << stu.student_id << endl; // 訪問私有成員 }
}; int main() { Student stu(20230001); Teacher teacher; teacher.view_id(stu); // 教師類成員函數訪問學生類私有ID return 0;
}
注意事項
- 前向聲明:若友元函數所屬的類未定義,需提前聲明(如
class Teacher;
),但不能訪問其成員細節。 - 單向特權:僅被聲明的成員函數擁有訪問權,類 B 的其他成員函數仍無權限。
2. 友元類
定義與聲明
- 作用:將整個類 B 聲明為類 A 的友元,類 B 的所有成員函數均可訪問類 A 的私有 / 保護成員。
- 聲明方式:在類 A 內用
friend class B;
聲明類 B 為友元。
示例:友元類訪問私有成員
#include <iostream>
using namespace std; class Library; // 前向聲明 class Book {
private: string title; int page_count; public: Book(string t, int p) : title(t), page_count(p) {} // 聲明Library為友元類 friend class Library;
}; class Library {
public: void display_book_info(Book& b) { // 訪問Book的私有成員 cout << "書名:" << b.title << ", 頁數:" << b.page_count << endl; }
}; int main() { Book book("C++ Primer", 1000); Library lib; lib.display_book_info(book); // 合法!友元類成員函數訪問私有成員 return 0;
}
友元類的特性
-
單向性:
- 若 A 是 B 的友元類,B 不一定是 A 的友元類,除非 A 也聲明 B 為友元。
class A { friend class B; }; // A允許B訪問自己的私有成員 class B { friend class A; }; // 需額外聲明,B才允許A訪問自己的私有成員
-
不可傳遞性:
- 若 B 是 A 的友元,C 是 B 的友元,C 并非自動成為 A 的友元。
-
破壞封裝性:
- 友元類可訪問所有私有成員,打破類的封裝邊界,需謹慎使用(僅在必要的類間協作時使用)。
3. 友元的優缺點與最佳實踐
(1)核心優勢
- 靈活協作:允許類間高效交互,避免通過公有接口間接訪問(如性能敏感場景)。
- 保留封裝性:僅對特定函數 / 類開放權限,而非完全公開私有成員。
(2)潛在風險
- 耦合度增加:友元關系會強化類間依賴,修改一方可能影響另一方。
- 調試難度:私有成員的訪問點分散在友元函數 / 類中,難以追蹤。
(3)使用建議
- 最小特權原則:優先聲明單個友元函數而非整個友元類,縮小特權范圍。
- 文檔說明:在友元聲明處注釋說明原因,提高代碼可讀性。
- 避免濫用:僅在必要時使用(如運算符重載、類間數據共享),優先通過公有接口實現。
總結:友元核心知識點
類型 | 定義 | 聲明方式 | 訪問權限 |
---|---|---|---|
非成員友元函數 | 全局函數,通過friend 聲明獲得類私有成員訪問權 | friend void func(類對象); | 可訪問類的所有成員(含私有) |
成員友元函數 | 其他類的成員函數,聲明后可訪問當前類私有成員 | friend void 類B::func(類A對象); | 僅該成員函數擁有訪問權 |
友元類 | 整個類的所有成員函數可訪問當前類私有成員 | friend class 類B; | 類 B 的所有成員函數均有訪問權 |
友元機制是 C++ 封裝性的補充,合理使用能在保持代碼結構的同時實現高效交互。但需注意控制特權范圍,避免過度依賴,確保代碼的可維護性和安全性。下一章節將深入探討拷貝構造函數與對象復制,理解對象創建的深層機制。
九、拷貝構造函數:對象的 “復制粘貼”
1. 自定義拷貝構造函數
- 語法:參數為當前類的
const引用
,避免遞歸調用。class String { private:char* str; public:String(char* s) { // 普通構造函數str = new char[strlen(s)+1];strcpy(str, s);}String(const String& obj) { // 拷貝構造函數str = new char[strlen(obj.str)+1];strcpy(str, obj.str); // 深拷貝,避免淺拷貝問題}~String() { delete[] str; } };
2. 默認拷貝構造函數
- 自動生成:若未定義,編譯器生成默認版本(淺拷貝),適用于無動態資源的類。
- 風險:若類包含動態內存,默認拷貝會導致多個對象指向同一塊內存,釋放時崩潰。
3. 調用場景
- 對象初始化:
String s2 = s1;
?或?String s2(s1);
- 函數傳參:
void func(String obj);
?調用時復制實參對象。 - 函數返回:
String func() { String s; return s; }
?返回時復制對象。
十、總結:類與對象核心知識點
概念 | 關鍵特性 |
---|---|
類的定義 | 封裝數據與行為,通過public/protected/private 控制訪問權限。 |
對象初始化 | 構造函數(含參數、初始化列表、重載),自動調用,初始化成員數據。 |
資源管理 | 析構函數釋放資源,避免內存泄漏,與構造函數成對出現。 |
數據共享 | 靜態成員(變量 / 函數)屬于類,所有對象共享,類外初始化。 |
權限突破 | 友元函數 / 類可訪問私有成員,打破封裝限制,需謹慎使用。 |
對象復制 | 拷貝構造函數實現深拷貝,避免默認淺拷貝的內存問題。 |
類型安全 | const 成員保證數據不被修改,常對象僅能調用常成員函數。 |
通過以上知識點,我們掌握了 C++ 類與對象的核心機制,從封裝數據到管理對象生命周期,再到靈活處理對象間的關系。后續將深入學習繼承與多態,進一步體會面向對象編程的強大能力。