類
在 C++ 中,類是一個關鍵概念,憑借其封裝和繼承的特性,能夠助力程序員之間實現高效的分工協作,共同完成復雜的大型項目。我們先從最簡單的概念入手,再進行更深層次的了解和應用。
1. 類的定義
類是用戶自定義的一種數據類型,它將數據和對數據進行操作的成員函數封裝在一起,用于表示現實世界中的事物或抽象概念。
1.1 類和函數有什么區別呢?
如果將程序比作一個工廠,函數就像是工廠中的各種機器,每臺機器完成特定的任務;而類就像是工廠中的工人,他們不僅攜帶工具(成員變量),還掌握技能(成員函數),可以獨立地完成復雜的任務。
如果是實現一個 獨立的、簡單的功能,且不需要管理狀態,使用函數可能更合適。**如果功能涉及到 數據和行為的結合,并且需要管理狀態,使用類會更合適。**如管理一個對象的狀態,用戶檔案。還比如需要將數據和操作封裝在一起,操作一些圖形,文件。或者說需要較為復雜的繼承,例如游戲角色的分化,從單純的角色分化為主角和各類小怪。
1.2 類和函數的例子
讓我們以一個銀行賬戶的數據管理為例,如果我們只是使用函數的話,那么有以下代碼:
#include <string>
#include <iostream>
using namespace std;int main()
{string liyang_name = "李陽"; // 李陽的賬戶名稱string liyang_number = "12345678"; // " 賬號long liyang_balance = 1000; // " 賬戶余額string zhouyan_name = "周燕"; // 周燕的賬戶名稱string zhouyan_number = "87654321"; // " 賬號long zhouyan_balance = 200; // " 賬戶余額liyang_balance -= 200; // 李陽取出 200 元zhouyan_balance += 100; // 周燕存入 100 元cout << "■李陽的賬戶:\"" << liyang_name << "\" (" << liyang_number << ") " << liyang_balance << "元\n";cout << "■周燕的賬戶:\"" << zhouyan_name << "\" (" << zhouyan_number << ") " << zhouyan_balance << "元\n";
}
在這里,我們想要用不同的賬戶進行存取,只能在變量名的命名中進行變化,每次都要建立新的變量,管理十分復雜。那么我們試著將賬戶看作一個類,這個類里面有各種成員,每個成員代表了不同的賬戶屬性。當想要建立用戶的賬戶時,就相當于建立了一個實體對象。每進行一次存取,就是存入一個數據,就只需要那么只需要操作這一個實體對象里面的數據即可。
如果我們使用類去存儲數據,就可以使用下面的代碼:
#include <string>
#include <iostream>
using namespace std;class Account {//聲明類的名字和成員
public:// 先不用管,還沒有學到string name; // 賬戶名稱string number; // 賬號long balance; // 賬戶余額
};int main()
{Account liyang; // 李陽的賬戶Account zhouyan; // 周燕的賬戶liyang.name = "李陽"; // 李陽的賬戶名稱liyang.number = "12345678"; // 賬號liyang.balance = 1000; // 賬戶余額zhouyan.name = "周燕"; // 周燕的賬戶名稱zhouyan.number = "87654321"; // 賬號zhouyan.balance = 200; // 賬戶余額liyang.balance -= 200; // 李陽取出200元zhouyan.balance += 100; // 周燕存入100元cout << "■李陽的:賬戶" << liyang.name << " (" << liyang.number<< ") " << liyang.balance << "元\n";cout << "■周燕的賬戶:" << zhouyan.name << " (" << zhouyan.number<< ") " << zhouyan.balance << "元\n";
}
而怎樣理解類和對象的關系呢?就可以概括為類是抽象的,而對象是類的實體。就是月餅模具和月餅本身的關系,而你想選擇的餡料和餅皮材料便是對象的實體數據,不一樣的材料,做出了不一樣的月餅,也便有了不一樣的月餅。
2. 類的成員-變量與函數
1.成員變量與成員函數
類的主體由成員變量和成員函數組成,以上個銀行賬戶管理系統的代碼為例,這里面只有成員變量,并沒有成員函數。那么我們每次存錢或者取錢的時候,要在main函數中手動進行加減余額,這相當于多了一次理解的規則,每次存入100元錢相當于要使用這個命令balance += 100,那么如果將這個命令直接變為語言可以理解的規則,我們直接使用deposit(100) (deposit英文釋義:存入) 這個語句,就可以直接讓銀行余額變多100元了。這里就可以使用成員函數來實現這件事了。
//在類中寫下存入函數void deposit(long amnt) {crnt_balance += amnt;}//在main函數中直接調存入函數zhouyan.deposit(100); // 周燕存入100元
3. 公有成員函數與私有成員變量
類中的成員變量和成員函數,它們通過訪問限定符來控制外部對它們的訪問權限, 分別為private(私有)、protected(受保護)或 public(公有)。私有成員只能在類的內部被訪問。類的外部代碼和派生類都不能直接訪問私有成員。受保護成員只能在類的內部和派生類(子類)中被訪問。類的外部代碼不能直接訪問受保護成員。公有成員可以在類的外部被訪問。任何對象都可以直接訪問公有成員。
這種分類并不是固定的,而是根據設計需求來決定的。不過,通常情況下,成員變量被聲明為 private,成員函數被聲明為 public,這種設計有其合理性和優勢。成員變量的私有保證了數據的封裝性,外部代碼不可以修改數據的類型;成員函數作為類的接口,可以通過外部代碼與類的對象進行交互。
class Account {
private:string full_name; // 賬戶名稱string number; // 賬號long crnt_balance; // 賬戶余額public:// 返回賬戶名稱string name() {return full_name;}// 返回賬號string no() {return number;}// 返回賬戶余額long balance() {return crnt_balance;}// 存入void deposit(long amnt) {crnt_balance += amnt;}// 取出void withdraw(long amnt) {crnt_balance -= amnt;}
};
4. 構造函數
在成員函數中,必須要有的便是構造函數,構造函數是C++中的一種特殊函數,它在創建對象時自動被調用,用于初始化對象。構造函數的名稱必須與類名相同,并且沒有返回類型(包括void)。構造函數的主要作用是為對象的成員變量賦初值,確保對象在創建時處于一個已知的、有效的狀態。
class Account {
private:string full_name; // 賬戶名稱string number; // 賬號long crnt_balance; // 賬戶余額public:// 構造函數Account(string name, string num, long amnt) {full_name = name; // 賬戶名稱number = num; // 賬號crnt_balance = amnt; // 賬戶余額}
};int main()
{Account liyang("李陽", "12345678", 1000); // 初始化李陽的賬戶Account zhouyan("周燕", "87654321", 200); // 初始化周燕的賬戶
/
}
5.完整的示例代碼及其類的成員
// 銀行賬戶類(第2版)及類的使用例程
#include <string>
#include <iostream>
using namespace std;class Account {
private:string full_name; // 賬戶名稱string number; // 賬號long crnt_balance; // 賬戶余額public:// 構造函數Account(string name, string num, long amnt) {full_name = name; // 賬戶名稱number = num; // 賬號crnt_balance = amnt; // 賬戶余額}// 返回賬戶名稱string name() {return full_name;}// 返回賬號string no() {return number;}// 返回賬戶余額long balance() {return crnt_balance;}// 存入void deposit(long amnt) {crnt_balance += amnt;}// 取出void withdraw(long amnt) {crnt_balance -= amnt;}
};int main()
{Account liyang("李陽", "12345678", 1000); // 李陽的賬戶Account zhouyan("周燕", "87654321", 200); // 周燕的賬戶liyang.withdraw(200); // 李陽取出200元zhouyan.deposit(100); // 周燕存入100元cout << "■李陽的賬戶:" << liyang.name() << " (" << liyang.no()<< ") " << liyang.balance() << "元\n";cout << "■周燕的賬戶:" << zhouyan.name() << " (" << zhouyan.no()<< ") " << zhouyan.balance() << "元\n";
}