目錄
1.類和對象
1.1 類的定義
1.2 訪問限定符
1.3 類域
?2.實例化
2.1 實例化概念
2.2 對象大小?
內存對齊規則?
3.this指針
1.類和對象
1.1 類的定義
(1)class為定義類的關鍵字,Stack為類的名字,{}中為類的主體,注意類定義結束時后?分號不能省略。類體中內容稱為類的成員:類中的變量稱為類的屬性或成員變量; 類中的函數稱為類的?法或者成員函數。
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Stack
{
public:// 成員函數void Init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申請空間失敗");return;}capacity = n;top = 0;}void Push(int x){// ...擴容arr[top++] = x;}int Top(){assert(top > 0);return array[top - 1];}void Destroy(){free(array);array = nullptr;top = capacity = 0;}private:int* arr;int size;int capacity;
};
int main()
{Stack st;st.Init();st.Push(1);st.Push(2);cout << st.Top() << endl;st.Destroy();return 0;}
(2)為了區分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加_ 或者 m開頭,注意C++中這個并不是強制的,只是?些慣例,具體看公司的要求。
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
private:
// 為了區分成員變量,?般習慣上成員變量
// 會加?個特殊標識,如_ 或者 m開頭
int _year; // year_ m_year
int _month;
int _day;
};
int main()
{
Date d;
d.Init(2024, 3, 31);
return 0;
}
(3)C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是struct中可以定義函數,區別是使用struct定義的類的成員默認為public,而class定義的類的成員默認為private(public和private定義后面會講到),?般情況下我們還是推薦?class定義類。
#include<iostream>
using namespace std;
// C++升級struct升級成了類
// 1、類??可以定義函數
// 2、struct名稱就可以代表類型
// C++兼容C中struct的?法
typedef struct ListNodeC
{
struct ListNodeC* next;
int val;
}LTNode;
// 不再需要typedef,ListNodeCPP就可以代表類型
struct ListNodeCPP
{
void Init(int x)
{
next = nullptr;
val = x;
}
ListNodeCPP* next;
int val;
};
int main()
{
return 0;
}
?(4)定義在類?的成員函數默認為inline。
1.2 訪問限定符
?(1)C++?種實現封裝的?式,?類將對象的屬性與?法結合在?塊,讓對象更加完善,通過訪問權限選擇性的將其接?提供給外部的??使?。
(2)public修飾的成員在類外可以直接被訪問;protected和private修飾的成員在類外不能直接被訪問,protected和private是?樣的,以后繼承章節才能體現出他們的區別。
(3)問權限作?域從該訪問限定符出現的位置開始直到下?個訪問限定符出現時為?,如果后?沒有訪問限定符,作?域就到 }即類結束。
(4)class定義成員沒有被訪問限定符修飾時默認為private,struct默認為public。
(5)?般成員變量都會被限制為private/protected,需要給別?使?的成員函數會放為public。
【面試題】
問題:C++中struct和class的區別是什么?
解答:C++需要兼容C語言,所以C++中struct可以當成結構體使用。另外C++中struct還可以用來
定義類。和class定義類是一樣的,區別是struct定義的類默認訪問權限是public,class定義的類
默認訪問權限是private。注意:在繼承和模板參數列表位置,struct和class也有區別,后序給大
家介紹。
1.3 類域
(1)類定義了?個新的作?域,類的所有成員都在類的作?域中,在類體外定義成員時,需要使? :: 作?域操作符指明成員屬于哪個類域。
(2)類域影響的是編譯的查找規則,下?程序中Init如果不指定類域Stack,那么編譯器就把Init當成全局函數,那么編譯時,找不到array等成員的聲明/定義在哪?,就會報錯。指定類域Stack,就是知道Init是成員函數,當前域找不到的array等成員,就會到類域中去查找。
#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;
}
int main()
{
Stack st;
st.Init();
return 0;
}
?2.實例化
2.1 實例化概念
(1)?類類型在物理內存中創建對象的過程,稱為類實例化出對象。
(2)類是對象進??種抽象描述,是?個模型?樣的東西,限定了類有哪些成員變量,這些成員變量只是聲明,沒有分配空間,?類實例化出對象時,才會分配空間。
(3)?個類可以實例化出多個對象,實例化出的對象 占?實際的物理空間,存儲類成員變量。打個??:類實例化出對象就像現實中使?建筑設計圖建造出房?,類就像是設計圖,設計圖規劃了有多少個房間,房間??功能等,但是并沒有實體的建筑存在,也不能住?,?設計圖修建出房?,房?才能住?。同樣類就像設計圖?樣,不能存儲數據,實例化出的對象分配物理內存存儲數據。
代碼實例:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class Data
{
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和d2Data d1;Data d2;d1.Init(2024, 9,9);d1.print();d2.Init(1919, 5, 4);d2.print();return 0;
}
2.2 對象大小?
? ?分析?下類對象中哪些成員呢?類實例化出的每個對象,都有獨?的數據空間,所以對象中肯定包含成員變量,那么成員函數是否包含呢??先函數被編譯后是?段指令,對象中沒辦法存儲,這些指令存儲在?個單獨的區域(代碼段),那么對象中?要存儲的話,只能是成員函數的指針。
再分析?下,對象中是否有存儲指針的必要呢,Date實例化d1和d2兩個對象,d1和d2都有各?獨?的成員變量_year/_month/_day存儲各?的數據,但是d1和d2的成員函數Init/Print指針卻是?樣的,存儲在對象中就浪費了。
如果?Date實例化100個對象,那么成員函數指針就重復存儲100次,太浪費了。這?需要再額外啰嗦?下,其實函數指針是不需要存儲的,函數指針是?個地址,調?函數被編譯成匯編指令[call 地址], 其實編譯器在編譯鏈接時,就要找到函數的地址,不是在運?時找,只有動態多態是在運?時找,就需要存儲函數地址,這個我們以后會講解
?
上?我們分析了對象中只存儲成員變量,C++規定類實例化的對象也要符合內存對?的規則。
內存對齊規則?
?(1)第?個成員在與結構體偏移量為0的地址處。
(2)其他成員變量要對?到某個數字(對?數)的整數倍的地址處。
(3)注意:對?數 = 編譯器默認的?個對?數 與 該成員??的較?值。
(4)VS中默認的對?數為8
(5)構體總??為:最?對?數(所有變量類型最?者與默認對?參數取最?)的整數倍。
(6)如果嵌套了結構體的情況,嵌套的結構體對?到??的最?對?數的整數倍處,結構體的整體??就是所有最?對?數(含嵌套結構體的對?數)的整數倍。
3.this指針
(1)Date類中有 Init 與 Print 兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調?Init和Print函數時,該函數是如何知道應該訪問的是d1對象還是d2對象呢?那么這?就要看到C++給了?個隱含的this指針解決這?的問題
(2)編譯器編譯后,類的成員函數默認都會在形參第?個位置,增加?個當前類類型的指針,叫做this指針。?如Date類的Init的真實原型為:?void Init(Date* const this, int year,int month, int day)
(3)類的成員函數中訪問成員變量,本質都是通過this指針訪問的,如Init函數中給_year賦值:?this->_year = year;
(4)C++規定不能在實參和形參的位置顯?的寫this指針(編譯時編譯器會處理),但是可以在函數體內顯示使?this指針。