前言
本系列文章承接C語言的學習,需要有C語言的基礎才能學會哦~
第3篇主要講的是有關于C++的類的定義、訪問限定符、類域、類的實例化和this指針。
C++才起步,都很簡單呢!
目錄
前言
類
基本語法
訪問限定符
基本語法
類域
類的實例化?
內存對齊規則
this指針
封裝(初步了解)
類
class為類的關鍵字,后跟類名,{ }中為類的主體。主體中內容稱為類的成員,類中的變量稱為類的屬性或者成員變量,類中的函數稱為方法或者成員函數。
基本語法
為了區分方法的形參和類中的成員變量,通常會在變量前后加一個下劃線,具體怎么標識,看公司或者團隊要求。
//類與對象
class Stack
{//方法void Init(int capacity = 4){_array = (int*)malloc(sizeof(int) * capacity);if (nullptr == _array){perror("malloc申請空間失敗!\n");return;}_capacity = capacity;_top = 0;}void Push(int x){//擴容步驟(省略)_array[_top++] = x;}//·······(省略棧的各種函數)//成員變量int* _array;size_t _capacity;size_t _top;
};
//類名就是類型
類中的成員函數,默認為inline函數。
訪問限定符
①public公有,在類外可以直接被訪問。設計時成員函數一般是公有的。
②private私有,在類外不能直接被訪問。設計時成員變量一般是私有的。
③protect保護,在類外不能直接被訪問。在繼承上,和private有區別(在繼承詳細說明)。
基本語法
class Stack
{
//公有
public:void Init(int capacity = 4){_array = (int*)malloc(sizeof(int) * capacity);if (nullptr == _array){perror("malloc申請空間失敗!\n");return;}_capacity = capacity;_top = 0;}
//私有
private:int* _array;size_t _capacity;size_t _top;
};
如上,跟在不同的訪問限定符后,受不同的訪問限定。
?
C++兼容C語言的struct,同時又升級了struct。
C++中,struct和類的唯一區別在于:struct的成員變量和方法默認為public,class默認為private。為求嚴謹,最好自己指明訪問限定符。
//不加訪問限定符,默認為public
struct Person
{void Init(const char name[5]){strcpy(_name,name);}void Print(){cout << "姓名:" << _name << endl;}char _name[5];
};int main()
{//可在外部直接使用Person p1;p1.Init("張三");p1.Print();return 0;
}
類域
由類定義的一個新的作用域,類的所有成員都在類域中。類域使得不同的類可以有同名的成員。和命名空間類似,它影響的是編譯器的查找順序規則(具體去看我博客內的C++第一篇喔~)。
成員函數可以進行聲明和定義的分離。
一般我們將聲明放在類中,定義放在另一個文件中。并且為了標識該方法所屬的類,需要用到域作用限定符? ::?。
void Stack::Init(int capacity)//注意定義處不要寫缺省參數,缺省參數寫在聲明
{//函數實現省略···
}
類的實例化?
類中的成員變量在沒有實例化時,均不開辟空間,只是一個聲明。我們要將類實例化成對象后,它才能夠存儲數據,我們才能對具體的對象進行操作。
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;//實例化出對象d1Date d2;//實例化出對象d2d1.Init(2025, 7, 20);d2.Init(2025, 7, 25);d1.Print();d2.Print();cout << sizeof(d1) << endl;//輸出12,成員變量共12個字節cout << sizeof(d2) << endl;//輸出12,成員變量共12個字節return 0;
}
實例化后,對象只存儲成員變量,不存儲方法指針。因為同一類的對象使用的是相同的方法,所以將方法存儲在公共代碼區即可,不存儲在實例對象里。否則,會重復存儲,浪費空間。
內存對齊規則
成員變量存儲,遵循C語言的內存對齊規則。
①第一個成員變量在類起始地址偏移量為0處。
②其他成員變量要對齊到對齊數的整數倍地址處。
③對齊數 = 編譯器默認對齊數 與 該成員大小 的較小值。
④VS編譯器默認的對齊數是8。
⑤類的總大小為默認對齊數的整數倍。
⑥類中沒有成員時(如仿函數類),總大小為1byte。即使沒有也要開辟空間占位,以表示存在實例對象。
內存對齊的目的:方便讀取,讀取數據時可以從在數據類型大小的整數倍位置讀取,不用一字節一字節讀,而是跳躍讀取,找到位置后可以一次性讀取,不用再一個字節一個字節拼起來。
this指針
用于指明類方法中區分訪問的成員方法。類方法存儲在公共代碼區,在類方法的角度來看,調用它時,該方法并不清楚是哪個對象調用的它。這就要用到this指針。
類方法中實際上還會隱含一個參數,
void Init(int year, int month, int day)
{//略···
}//在形參列表首位,存在一個省略的參數this指針
void Init(Date* const this, int year, int month, int day)
{//略···
}
我們可以看到有const修飾,該隱藏參數是不可以修改的。
調用時,會傳入調用方法的對象的地址作為this指針
d1.Init(2025, 7, 21);
//d1.Init(&d1, 2025, 7,21);
//實際上是這樣傳參的,但是不能這樣寫
?C++編譯器會自動添加的隱含的this,程序員不可以自行添加,會報錯。但是可以在函數體內添加使用。
void Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}
//等價于
void Print()
{cout << this->_year << "/" << this->_month << "/" << this->_day << endl;
}
通過this指針,對象調用類方法時,才可以在類方法內訪問對象的屬性。
類指針的易錯點:
class A
{
public:void Print(){cout << "Hi!" << endl;}
private:int _a;
};class B
{
public:void Print(){cout << "Hi!" << endl;cout << _b << endl;}
private:int _b;
};int main()
{//正常運行,輸出“Hi!”A* pa = nullptr;pa->Print();//運行崩潰B* pb = nullptr;pb->Print();return;
}
如上,pa和pb都是空指針。
pa指針調用Print方法能正常運行,是因為運行時未對這個空指針進行解引用操作。
pb指針調用Print方法會運行崩潰,是因為運行到語句 cout << _b << endl 時,_b前有隱藏的this指針,所以這里實際上有一個 this->_b ,這里的this即是傳入的pb空指針,發生解引用錯誤。
(“ 指針-> ”為解引用操作喔~)
ps:this指針的創建在棧區
封裝(初步了解)
目的:C++將數據和函數放在類中,隱藏細節和復雜部分,只需要確保代碼能實現目的即可。靠訪問限定符,約束和管理程序員訪問數據,避免細節上的錯誤。
關于封裝更多的知識,在之后還有更多可以學習的,敬請關注!!
?~~本文完結!!感謝觀看!!歡迎來我博客做客~~?