ovz的vps怎么做網(wǎng)站建設(shè)企業(yè)網(wǎng)站多少錢
目錄
類的認(rèn)識
訪問限定符:public(公有),protected(保護(hù)),private(私有)。
類的兩種定義方式:
類的實(shí)例化:
封裝:
類的對象大小的計(jì)算:
類成員函數(shù)的this指針:
C語言是面向過程的語言,關(guān)注的是過程,分析求解問題的步驟,通過函數(shù)調(diào)用逐步解決問題。
C++是基于面向?qū)ο蟮恼Z言,關(guān)注的是對象,將一件事拆分成不同的對象,考對象之間的交互完成。
C語言結(jié)構(gòu)體struct中只能定義變量,在C++中,結(jié)構(gòu)體內(nèi)不僅可以定義變量,也可以定義函數(shù),因?yàn)镃++將struct同時(shí)升級成了類,類中可以定義函數(shù)。
如下:
struct Stack
{int* _a;int _top;int _capacity;void Init() {_a = 0;_top = 0;_capacity = 0;}
};
在C++中類名就是類型,所以C++在聲明結(jié)構(gòu)體變量時(shí)不需要在前面加struct,使用上面的Stack定義,如:Stack s1;
類的認(rèn)識
在C++中更喜歡用class來代替。
class className{
????????//類體:由成員函數(shù)和成員變量組成
};//注意分號
class為定義的關(guān)鍵字,ClassName為類的名字,{}中為類的主體,類定義結(jié)束時(shí)后面分號不能省略。
類體中內(nèi)容稱為類的成員:類中的變量稱為類的屬性或成員變量,類中的函數(shù)稱為類的方法或者成員函數(shù)。
訪問限定符:public(公有),protected(保護(hù)),private(私有)。
- public修飾的成員在類外可以直接被訪問。
- protected和private修飾的成員在類外不能直接被訪問。
- 訪問權(quán)限作用域從該訪問限定符出現(xiàn)的位置開始直到下一個(gè)訪問限定符出現(xiàn)時(shí)為止。
- 如果后面沒有訪問限定符,作用域就到}即結(jié)束。
- class的默認(rèn)訪問權(quán)限為private,struct為public(因?yàn)樵贑中的struct在類外都可以訪問所以是公有)。
- 注意:訪問限定符只在編譯時(shí)有用,當(dāng)數(shù)據(jù)映射到內(nèi)存后,沒有任何訪問限定符上的區(qū)別。
如下代碼:
class Stack
{
private:int* _a;int _top;int _capacity;
public:void Init() {_a = 0;_top = 0;_capacity = 0;}bool Empty() {return _top == 0;}
};
其中private下面的為私有的在類外不可以訪問,public下面的為公有在類外都可以訪問。如果我在類外修改類內(nèi)的a只需要調(diào)用公有成員Init()函數(shù)就可以修改了。因?yàn)镮nit是在類內(nèi)的所以他可以訪問類內(nèi)的私有成員。但是不能在類外直接訪問成員a。
類的兩種定義方式:
- 1.聲明和定義全部放在類體中。注意:成員函數(shù)如果在類中定義,編譯器可能會將其當(dāng)成內(nèi)聯(lián)函數(shù)處理。如下聲明和定義全部放在類體中:
-
class Person{ public://顯示基本信息void showlnfo(){cout<<_name<<"-"<<_sex<<"-"<<_age<<endl;} public:char*_name;//姓名char*_sex;//性別int _age;//年齡 };
- 2.類聲明放在.h文件中,成員函數(shù)定義放在.cpp文件中。注意:成員函數(shù)名前面需要加類名::。
- 聲明放在類的頭文件person.h中:
-
class Person{ public://聲明void showlnfo(); public:char*_name;//姓名char*_sex;//性別int _age;//年齡 };
-
定義放在實(shí)現(xiàn)文件person.cpp中,在showlnfo函數(shù)名前面加了Person::,表示showlnfo是Person類中的,如下:
-
#include"person.h" //顯示基本信息,輸出名字,性別,年齡; void Person::showlnfo(){cout<<_name<<"-"<<_sex<<"-"<<_age<<endl; }
一般情況,采用第二種方式。
類的作用域:類定義了一個(gè)新的作用域,類的所有成員都在類的作用域中,在類體外定義成員時(shí),需要使用::作用域操作符指明成員屬于哪個(gè)類域。在C++中{}定義的都是域。
類的實(shí)例化:
用類類型創(chuàng)建對象的過程,稱為類的實(shí)例化。
- 類是對對象進(jìn)行描述的,是一個(gè)模型一樣的東西,限定了類有哪些成員,定義處一個(gè)類并沒有分配實(shí)際的內(nèi)存空間來存儲。
- 一個(gè)類可以實(shí)例化多個(gè)對象,實(shí)例化出的對象,占用實(shí)例的物理空間,存儲類成員變量。
class Person{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int _age;
};
//這里需要指定PrintPersonInfo是屬于Person這個(gè)類域
void Person::PrintPersonInfo(){cout<<_name<<" "<<_gender<<" "<<_age<<endl;
}
若要使用Person類,需要先實(shí)例化,然后才能使用。
下列寫法是有誤的:
Person._name=0;? ?//沒有創(chuàng)建類的變量,也就是_name根本沒有空間,所以無法訪問。
你可以這樣認(rèn)為類只是圖紙,而創(chuàng)建類則是根據(jù)圖紙建好的房子。
封裝:
封裝是將數(shù)據(jù)和操作數(shù)據(jù)的方法進(jìn)行結(jié)合,隱藏對象的實(shí)現(xiàn)細(xì)節(jié),僅對外公開接口來和對象進(jìn)行交互。封裝本質(zhì)是一種管理,比如電腦提供給用戶僅有關(guān)開機(jī),鍵盤,顯示器..等,剩下的CPU,顯卡,都封裝了。
在C++中實(shí)現(xiàn)封裝,可以通過類將數(shù)據(jù)以及操作數(shù)據(jù)的方法進(jìn)行結(jié)合,通過訪問權(quán)限來隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié),控制方法在類外直接被調(diào)用。
如我在類中有成員_name,_age為私有的把他們隱藏起來,然后再提供一個(gè)共有的void PrintPersonInfo(){}函數(shù)用來控制類內(nèi)的成員,然后再外調(diào)用這個(gè)函數(shù),這時(shí)這個(gè)函數(shù)就是類提供給外面的接口。
類的對象大小的計(jì)算:
如類創(chuàng)建變量時(shí)申請了內(nèi)存,那么我們該如何計(jì)算類的大小,如下有幾種猜測:
- 1.對象包含類的各個(gè)成員 :
- 缺陷:每個(gè)對象中的成員變量的值是不同的,但是調(diào)用同一份相同代碼的函數(shù),如果此種方式存儲那么當(dāng)一個(gè)類創(chuàng)建多個(gè)對象時(shí),每個(gè)對象都會保存一份的代碼,相同代碼保存多次,浪費(fèi)空間。
- 2.代碼只保存一份,再對象中保存存放代碼的地址:
- 3.只保存成員變量,成員函數(shù)存放在公共的代碼段:
對于上述三種方式,我們可以通過不同對象分別獲取大小來分析,如下:
class A1{public:void f1(){}private:int _a;};//類中僅有成員函數(shù)class A2{public:void f2(){}};
// 類中什么都沒有--空類class A3{};int main() {cout << "A1:" << sizeof(A1) << endl;cout << "A2:" << sizeof(A2) << endl;cout << "A3:" << sizeof(A3) << endl;}
代碼結(jié)果為sizeof(A1)=4 ,sizeof(A2)=1,sizeof(A3)=1。
由此可以知道:一個(gè)類的大小,實(shí)際就是該類中"成員變量"之和,不是函數(shù),注意內(nèi)存對齊。
注意空類的大小,空類比較特殊,編譯器會給空類一個(gè)字節(jié)來唯一標(biāo)識這個(gè)類的對象
?結(jié)構(gòu)體內(nèi)存對齊規(guī)則:
- ?第一個(gè)成員在與結(jié)構(gòu)體偏移量為0的地址處。
- ?其他成員變量要對齊到某個(gè)數(shù)字(對齊數(shù))的整數(shù)倍的地址處
- ?注意:對齊數(shù)=編譯器默認(rèn)的一個(gè)對齊數(shù) 與該成員的大小較小值
- ?VS中默認(rèn)的對齊數(shù)為0
- ?結(jié)構(gòu)體總大小為:最大對齊數(shù)(所有變量類型最大者與默認(rèn)對齊參數(shù)取最小)的整數(shù)倍。
- ?如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對齊數(shù)(行嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍。
類成員函數(shù)的this指針:
this指針的引出:
如下有一串代碼:
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;Date d2;Date d3;d1.Init(2023, 10, 7);d2.Init(2022, 10, 7);d1.Print();d2.Print();return 0;
}
? ? 對于上述代碼有這樣一個(gè)問題:Date類中有Init和Print兩個(gè)成員函數(shù),函數(shù)體沒有關(guān)于不同對象的區(qū)別,那么當(dāng)d1調(diào)用Init函數(shù)時(shí),該函數(shù)是如何知道應(yīng)該設(shè)置d1對象,而不是設(shè)置d2對象呢。
在C++通過引入this解決了該問題:C++編譯器給每個(gè)"非靜態(tài)的成員函數(shù)"增加了一個(gè)隱藏的指針參數(shù),讓該指針指向當(dāng)前對象(函數(shù)運(yùn)行時(shí)調(diào)用該函數(shù)的對象),在函數(shù)體中所有"成員變量的操作",都是通過該指針去訪問,只不過所有操作對用戶是透明的,即用戶不需要來傳遞,編譯器自動完成。
如上述調(diào)用d1.Print();的代碼會被編譯器處理成如下代碼:
?d1.Print(); //處理之后 d1.Print(&d1);void Print(){cout << _year << "-" << _month << "-" << _day << endl; } //處理之后 void Print(Date*const this) {cout << this->_year << "-" <<this->?_month << "-" <<this-> _day << endl; }
注意:
- this不能顯示的寫this相關(guān)的形參和實(shí)現(xiàn)。上述是編譯器處理后的結(jié)果:如
- void Print(Date*const this){}? ?this不能作為參數(shù)
- 但是可以在類里面顯示的使用,如:
- cout << this->_year << "-" <<this-> _month << "-" <<this-> _day << endl;
this指針的特性:
- this指針的類型:類類型*const,即成員函數(shù)中,不能該this指針賦值。
- 只能在"成員函數(shù)"的內(nèi)部使用。
- this指針的本質(zhì)上是"成員函數(shù)"的形參,當(dāng)對象調(diào)用成員函數(shù)時(shí),將對象地址作為實(shí)參傳遞給this形參,所以對象中不存儲this指針。
- this指針是"成員函數(shù)"第一個(gè)隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要用戶傳遞。
- this指針在VS中是存儲到棧幀上面的。
- this指針可以為空。