類與對象(中)
1.面向過程和面向對象初步認識
C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數調用逐漸解決問題。
C++是基于面向對象的,關注的是對象,将一件事情拆分成不同的對象,靠對象之間的互動完成。
2.類的引入
C語言中,結構體中隻能定義變量,
C++中,結構體内不僅可以定義變量,也可以定義函數。
結構體的定義,在C++中更喜歡用class來代替
3.類的定義
class className
{
// 類體:由成員函數和成員變量組成
}; // 一定要注意後面的分号
class為定義類的關鍵字,ClassName為類的名字,{}中為類的主體,注意類定義結束時後面分号。
類中的元素稱為類的成員:類的資料稱為類的屬性或者成員變量; 類中的函數稱為類的方法或者成員函數。
類的兩種定義方式:
1.聲明和定義全部放在類體中,需要注意:成員函數如果在類中定義,編譯器可能會将其當成内聯函數處理。
聲明和定義全部放在類體中:
class Person
{
public:
void showInfo()
{
cout<<_name<<"-"<<_sex<<"-"<<_age<<endl;
}
public:
char*_name;
char*_sex;
int _age;
};
-
聲明放在.h檔案中,類的定義放在.cpp檔案中
聲明放在類的頭檔案person.h中:
class Person
{
public:
void showInfo();
public:
char*_name;
char*_sex;
int _age;
};
定義放在類的實作檔案person.cpp中:
#inclue "Person.h"
void Person::showInfo()
{
cout<<_name<<"-"<<_sex<<"-"<<_age<<endl;
}
一般情況下,更期望采用第二種方式。
4.類的通路限定符及封裝
4.1 通路限定符
C++實作封裝的方式:用類将對象的屬性與方法結合在一塊,讓對象更加完善,通過通路權限選擇性的将其接口提供給外部的使用者使用。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL0gzYklzMhBTMhJTOxUjNhVGMiRTZ2IjMzQWN3QmYkRzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
【通路限定符說明】
- public修飾的成員在類外可以直接被通路
- protected和private修飾的成員在類外不能直接被通路(此處protected和private是類似的)
- 通路權限作用域 :從該通路限定符出現的位置開始直到下一個通路限定符出現時為止
-
class的預設通路權限為private,struct為public(因為struct要相容C)
注意:通路限定符隻在編譯時有用,當資料映射到記憶體後,沒有任何通路限定符上的差別
C++中struct和class的差別?
C++需要相容C語言,是以C++中struct可以當成結構體去使用。另外C++中struct還可以用來定義類,和class是定義類是一樣的,差別是struct的成員預設通路方式是public,class是struct的成員預設通路方式是private。
4.2封裝
面向對象的三大特性:封裝、繼承、多态。
封裝:将資料和操作資料的方法進行有機結合,隐藏對象的屬性和實作細節,僅對外公開接口來和對象進行互動。
5.類的執行個體化
用類類型建立對象的過程,稱為類的執行個體化
- 類隻是一個模型一樣的東西,限定了類有哪些成員,定義出一個類并沒有配置設定實際的記憶體空間來存儲它
- 一個類可以執行個體化出多個對象,執行個體化出的對象占用實際的實體空間,存儲類成員變量
-
**類執行個體化出對象就像現實中使用建築設計圖建造出房子,類就像是設計圖,**隻設計出需要什麼東西,但是并沒有實體的建築存在,同樣類也隻是一個設計,執行個體化出的對象才能實際存儲資料,占用實體空間
一個類相當于一份圖紙,一份圖紙可以建造多個建築,一個類可以執行個體化多個對象
class Person
{
public:
void showInfo();
public:
char*_name;
char*_sex;
int _age;
};
void Test()
{
Person man;
man._name="jack";
man._sex="男";
man.showInfo();
}
6.類的作用域
類定義了一個新的作用域,類的所有成員都在類的作用域中。在類體外定義成員,需要使用 :: 作用域解析符指明成員屬于哪個類域。
class Person
{
public:
void PrintPersonInfo();
private:
char _name[20];
char _gender[3];
int _age;
};
// 這裡需要指定PrintPersonInfo是屬于Person這個類域
void Person::PrintPersonInfo()
{
cout<<_name<<" "_gender<<" "<<_age<<endl;
}
7.類的對象大小的計算
7.1 如何計算類對象的大小
class A
{
public:
void PrintA
{
cout<<_a<<endl;
}
private:
char _a;
};
類中既可以有成員變量,又可以有成員函數,如何計算一個類的大小?
每個對象中成員變量是不同的,但是調用同一份函數,如果按照此種方式存儲,當一個類建立多個對象時,每個對象中都會儲存一份代碼,相同代碼儲存多次,浪費空間。隻儲存成員變量,成員函數存放在公共的代碼段
一個類的大小,實際就是該類中”成員變量”之和,當然也要進行記憶體對齊,注意空類的大小,空類比較特殊,編譯器給了空類一個位元組來唯一辨別這個類。
7.3 結構體記憶體對齊規則
- 第一個成員在與結構體偏移量為0的位址處。
-
其他成員變量要對齊到某個數字(對齊數)的整數倍的位址處。
注意:對齊數 = 編譯器預設的一個對齊數 與 該成員大小的較小值。VS中預設的對齊數為8
- 結構體總大小為:最大對齊數(所有變量類型最大者與預設對齊參數取最小)的整數倍。
- 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。
8.類成員函數的this指針
8.1 this指針的引出
class Date
{
public :
void Display ()
{
cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}
void SetDate(int year , int month , int day)
{
_year = year;
_month = month;
_day = day;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
int main()
{
Date d1, d2;
d1.SetDate(2018,5,1);
d2.SetDate(2018,7,1);
d1.Display();
d2.Display();
return 0;
}
Date類中有SetDate與Display兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調用SetDate函數時,該函數是如何知道應該設定d1對象,而不是設定d2對象呢?
C++中通過引入this指針解決該問題即:
C++編譯器給每個“非靜态的成員函數“增加了一個隐藏的指針參數,讓該指針指向目前對象(函數運作時調用該函數的對象),在函數體中所有成員變量的操作,都是通過該指針去通路。隻不過所有的操作對使用者是透明的,即使用者不需要來傳遞,編譯器自動完成。
8.2 this指針的特性
- this指針的類型:類 類型* const
- 隻能在“成員函數”的内部使用
- this指針本質上其實是一個成員函數的形參,是對象調用成員函數時,将對象位址作為實參傳遞給this形參。是以對象中不存儲this指針。
- this指針是成員函數第一個隐含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要使用者傳遞
void Display()
{
cout<<_year<<endl;
}
void Display(Date*this)
{
cout<<this->_year<<endl;
}