C++ 類與對象詳解:從結構體到面向對象編程
C++ 的面向對象編程(OOP)核心是?類(Class)?和?對象(Object)。類是用戶自定義的數據類型,用于封裝數據(屬性)和操作數據的方法(行為);對象則是類的實例。本文將從?C 風格結構體?引入,逐步深入講解 C++ 的類和對象,結合代碼和詳細說明。
1. 從 C 風格結構體到 C++ 類
1.1 C 風格結構體(Struct)
在 C 語言中,結構體(struct
)用于將多個相關變量組合成一個復合類型:
#include <iostream>
#include <cstring> // 用于 strcpy// C 風格結構體:表示一個學生
struct StudentC {char name[50]; // 姓名(字符數組)int age; // 年齡float score; // 分數
};int main() {// 創建結構體變量并初始化StudentC s1;strcpy(s1.name, "Alice"); // C 風格字符串賦值s1.age = 20;s1.score = 95.5f;// 訪問結構體成員std::cout << "Name: " << s1.name << ", Age: " << s1.age << ", Score: " << s1.score << std::endl;return 0;
}
說明:
數據完全公開,無法控制訪問權限
操作數據的行為(函數)與數據本身分離(結構體僅包含數據,操作需額外函數實現)
缺乏數據保護機制,容易導致非法修改
1.2 C++ 結構體(增強版)
C++ 保留了?struct
,但允許在結構體內定義函數(方法),并支持訪問控制(public
/private
):
#include <iostream>
#include <string> // 使用 std::string 替代字符數組// C++ 結構體(帶方法)
struct StudentCpp {std::string name; // 更安全的字符串int age;float score;// 結構體內定義方法:打印學生信息void printInfo() {std::cout << "Name: " << name << ", Age: " << age << ", Score: " << score << std::endl;}
};int main() {StudentCpp s2;s2.name = "Bob"; // 直接賦值s2.age = 21;s2.score = 88.0f;s2.printInfo(); // 調用結構體方法return 0;
}
說明:
- C++ 的?
struct
?默認成員是?public
?的(與?class
?默認?private
?不同)。 - 可以在結構體內定義方法,但通常更推薦用?
class
?表達面向對象概念。
1.3 從結構體到類的關鍵轉變
C++ 中?class
?和?struct
?的唯一區別是默認訪問權限不同:
類是結構體的升級版,通過?訪問修飾符?控制成員的可見性,并強制將數據和方法綁定在一起:
// 使用 class 關鍵字
class Point {int x; // 默認 privateint y; // 默認 privatepublic:void print() {cout << "(" << x << ", " << y << ")" << endl;}void set(int newX, int newY) {if (newX >= 0 && newY >= 0) { // 添加驗證邏輯x = newX;y = newY;}}int getX() const { return x; } // const 成員函數int getY() const { return y; }
};int main() {Point p1;p1.set(3, 4);// p1.x = 5; // 錯誤:x 是 private 成員cout << p1.getX() << endl; // 正確:通過公共接口訪問return 0;
}
關鍵概念:
封裝:將數據和行為組合在一起,并控制訪問權限
訪問修飾符:
public
:公開的,任何代碼都可以訪問private
:私有的,只有類內部可以訪問protected
:受保護的,類內部和派生類可以訪問
const 成員函數:承諾不修改對象狀態的成員函數
2. 類的核心特性詳解
2.1?構造函數與初始化
基本構造函數
- 構造函數:
- 特殊方法,在創建對象時自動調用,用于初始化數據。
- 語法:
ClassName(參數列表) : 初始化列表 {}
。
class Student {string name;int age;double score;public:// 構造函數Student(const string& n, int a, double s) {name = n;age = a;score = s;}void display() const {cout << name << ", " << age << "歲, 成績: " << score << endl;}
};int main() {Student stu("張三", 18, 90.5); // 調用構造函數stu.display();return 0;
}
初始化列表(更高效的初始化方式)
class Student {string name;int age;double score;public:// 使用初始化列表的構造函數Student(const string& n, int a, double s) : name(n), age(a), score(s) { // 初始化列表// 構造函數體}
};
初始化列表的優勢:
對于類類型成員,直接調用拷貝構造函數而非先默認構造再賦值
對于 const 成員和引用成員,必須在初始化列表中初始化
執行效率更高
默認構造函數
class Student {// ... 其他成員同上public:Student() : name("無名"), age(0), score(0) {} // 默認構造函數// 也可以使用默認參數實現Student(const string& n = "無名", int a = 0, double s = 0) : name(n), age(a), score(s) {}
};int main() {Student stu1; // 調用默認構造函數Student stu2("李四"); // 使用默認參數return 0;
}
2.2 靜態成員(類共享數據)
靜態成員屬于類本身,而非單個對象,所有對象共享同一份數據:
#include <iostream>class Student {
private:static int studentCount; // 靜態成員:記錄學生總數std::string name;public:Student(const std::string& n) : name(n) {studentCount++; // 創建對象時增加計數}static int getStudentCount() { // 靜態方法:訪問靜態成員return studentCount;}
};// 初始化靜態成員(必須在類外定義)
int Student::studentCount = 0;int main() {Student s6("Eve");Student s7("Frank");std::cout << "Total Students: " << Student::getStudentCount() << std::endl; // 輸出 2return 0;
}
說明:
- 靜態成員需在類外單獨定義和初始化。
- 靜態方法只能訪問靜態成員,不能訪問非靜態成員。
3. 對象:類的實例
3.1 對象的創建與銷毀
對象是類的實例,通過構造函數初始化,析構函數清理資源:
#include <iostream>class Resource {
public:Resource() {std::cout << "Resource acquired!" << std::endl;}~Resource() { // 析構函數std::cout << "Resource released!" << std::endl;}
};int main() {{Resource res; // 創建對象,調用構造函數// ... 使用 res ...} // 離開作用域,自動調用析構函數return 0;
}
輸出:
Resource acquired!
Resource released!
析構函數特點:
名稱是?
~
?加類名,無參數無返回值在對象生命周期結束時自動調用
用于釋放資源、清理內存等收尾工作
如果不顯式定義,編譯器會生成默認析構函數
3.2 對象作為函數參數
對象可以通過值傳遞、引用傳遞或指針傳遞:
#include <iostream>class Point {
public:int x, y;Point(int xVal, int yVal) : x(xVal), y(yVal) {}
};// 1. 值傳遞(拷貝對象)
void printPointByValue(Point p) {std::cout << "Value: (" << p.x << ", " << p.y << ")" << std::endl;
}// 2. 引用傳遞(避免拷貝)
void printPointByRef(const Point& p) {std::cout << "Ref: (" << p.x << ", " << p.y << ")" << std::endl;
}int main() {Point p1(10, 20);printPointByValue(p1); // 拷貝 p1printPointByRef(p1); // 直接引用 p1return 0;
}
建議:
- 大型對象使用?
const
?引用傳遞(避免拷貝開銷)。 - 需要修改對象時使用非?
const
?引用或指針。
4. 總結
概念 | 說明 |
---|---|
結構體(Struct) | C 風格數據組合,C++ 增強后支持方法,默認成員公開。 |
類(Class) | 封裝數據和方法,通過訪問修飾符控制可見性,支持構造函數/析構函數。 |
對象 | 類的實例,通過構造函數初始化,析構函數清理資源。 |
靜態成員 | 屬于類而非對象,所有對象共享同一份數據。 |
封裝性 | 通過私有數據和公有方法保護數據安全性。 |