類的定義
格式規范
class
為定義類的關鍵字,后有類名,類的主體存于{}
中;- 類定義結束時后面的分號不能省略;
- 類體的內容成為類的成員,類中的變量成為成員變量,函數成為方法或成員函數;
- C++兼容C語言的
struct
用法,同時將struct
升級成了類的用法(更推薦類)- 在類定義中直接定義一個成員函數(即在類聲明的花括號{}內直接給出函數體),編譯器會默認將這個成員函數視為inline。這樣做的好處是,如果成員函數非常簡單,編譯器可以優化代碼,通過內聯展開來提高程序的執行效率。
舉例代碼:
class Stack
{
public:// 成員函數void Init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申請空間失敗");return;}capacity = n;top = 0;private:// 成員變量int* array;size_t capacity;size_t top;
}; // 分號不能省略
訪問限定符
封裝的概念
封裝是OOP的一個基本原則,它指的是將數據(屬性)和操作這些數據的代碼(方法)組合在一起,形成一個單元。封裝的主要目的是隱藏內部實現的細節,只暴露出一個可以被外界訪問和操作的接口。
- 數據封裝:類定義了屬性(也稱為成員變量或字段),這些屬性代表了對象的狀態。封裝確保了這些屬性只能通過類提供的方法來訪問和修改,從而保護數據不被外部代碼直接訪問,避免數據被不當操作。
- 方法封裝:類還定義了方法(也稱為成員函數或行為),這些方法定義了可以對對象執行的操作。封裝確保了對象的行為是通過這些方法來實現的,而不是直接操作對象的內部狀態。
訪問限定符
- 隱藏實現細節:通過使用private訪問限定符,類的實現細節被隱藏起來,外部代碼不能直接訪問或修改對象的內部狀態,只能通過public方法來操作。
- 提供接口:public方法提供了一個接口,允許外部代碼以受控的方式與對象交互。這些方法可以包含對private成員的訪問和修改,但這些操作的細節對外部是不可見的。
- 繼承和多態性:protected訪問限定符允許子類訪問和修改父類的某些成員,這在實現繼承和多態性時非常有用。子類可以擴展或修改父類的行為,同時保持對外部代碼的封裝。
- 維護數據完整性:通過限制對屬性的直接訪問,封裝確保了數據的完整性和一致性。
- 促進模塊化:封裝使得代碼更加模塊化,每個類負責管理自己的數據和行為,減少了不同模塊之間的耦合。(高內聚、低耦合)
類域
類會定義一個新的作用域,類的所有成員都在類的作用域中,在類外定義成員時需要用
::
作用域操作符指明成員屬于哪個類域。
在類外定義成員函數:
#include<iostream>using namespace std;class Stack
{public:// 成員函數void Init(int n = 4);
private:// 成員變量int* array;size_t capacity;size_t top;};// 聲明和定義分離,需要指定類域void Stack::Init(int n){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申請空間失敗");return;}capacity = n;top = 0;}
實例化
概念
類是一個藍圖或模板,它定義了一組屬性(成員變量)和方法(成員函數),這些屬性和方法共同描述了一類事物的特征和行為。而通過創建對象就可以將對象進行實例化,這一一種一對多的關系,一個類可以創造多個對象,每一個類都是一個個體實例,并不沖突。
// 如何實例化對象// 定義一個日期類
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "/" << _month << "/" << _day << endl;}
private:// 這?只是聲明,沒有開空間int _year;int _month;int _day;
};int main()
{// Date類實例化出對象d1和d2Date d1;Date d2;d1.Init(2024, 3, 31);d1.Print();d2.Init(2024, 7, 5);d2.Print();return 0;
}
對象??
對象中只存儲成員變量,每個成員函數在對象調用的時候用的都是同一個指針來訪問。對于對象的大小,要符合內存對齊的規則,關于內存對齊的詳細運用理解可以點擊藍字閱讀我的另一篇博客,具體的規則大概如下:
? 第?個成員在與結構體偏移量為0的地址處。
? 其他成員變量要對?到某個數字(對?數)的整數倍的地址處。
? 注意:對?數 = 編譯器默認的?個對?數 與 該成員??的較?值。
? VS中默認的對?數為8
? 結構體總??為:最?對?數(所有變量類型最?者與默認對?參數取最?)的整數倍。
? 如果嵌套了結構體的情況,嵌套的結構體對?到??的最?對?數的整數倍處,結構體的整體?? 就是所有最?對?數(含嵌套結構體的對?數)的整數倍。
?不要忘記內存對齊的目的:為了減少CPU訪問內存次數,提高效率。
this指針
編譯器編譯后,類的成員函數默認都會在形參第?個位置,增加?個當前類類型的指針,叫做
this指針
。?如Date類的Init的真實原型為,void Init(Date* const this, int year, int month, int day)
,但是C++規定不能在實參和形參位置上寫this指針
,但是可以在函數體內顯式使用this指針
。
- 類的成員函數中訪問成員變量,本質都是通過this指針訪問的,如Init函數中給
_year
賦值,this->_year = year;
。所以通過this指針
可以對于一個對象的維護更加便捷。
// 顯式使用this指針
void Init(int year, int month, int day)
{_year = year;this->_month = month;this->_day = day;
}
存儲位置
關于this指針
在內存上的存儲位置:當成員函數被調用時,this 指針通常存儲在調用棧上。調用棧是用于存儲函數調用時的局部變量和狀態信息的內存區域。