1. 程式人生 > >C++ 類和物件(上)

C++ 類和物件(上)

目錄

類的引入

類的定義

訪問限定符

封裝

類的作用域

類的例項化

引出

C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函式呼叫逐步解決問題。C++是基於面向物件的,關注的是物件,將一件事情拆分成不同的物件,靠物件之間的互動完成。

類的引入

從語言中struct結構體中只能定義變數,不能定義函式;而C++中即可以定義變數也可以定義函式。只不過在C++中給喜歡用class代替struct。

兩者區別:預設的繼承訪問許可權。struct是public的,class是private的;struct作為資料結構的實現體,它預設的資料訪問控制是public的,而class作為物件的實現體,它預設的成員變數訪問控制是private的。

類的定義

class為定義類的關鍵字,ClassName為類的名字,{}中為類的主體,注意類定義結束時後面分號。
類中的元素稱為類的成員:類中的資料稱為類的屬性或者成員變數; 類中的函式稱為類的方法或者成員函式。

class className
{
   //類體:成員函式+成員變數 
};

類的兩種定義方式:

1.宣告和定義全部放在類中,需要注意:成員函式如果在類中定義,編譯器可能會將其當成行內函數處理。

class Student
{
 public:
    void setInfo()
    {
         //.......
    }
 private:
     char* _name;
     char* _gender;
     int  _age;
}

2.宣告放在.h檔案,定義放在.cpp檔案,一般採用這種。

Student.h Stuent.cpp

class  Student{

public:

     void  setInfo();

 private:
     char* _name;
     char* _gender;
     int  _age;

}

}

void Student()

{

    //.............

}

類的訪問限定符及封裝

訪問限定符

訪問限定符說明:

1. public修飾的成員在類外可以直接被訪問
2. protected和private修飾的成員在類外不能直接被訪問(此處protected和private是類似的)
3. 訪問許可權作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時為止
4. class的預設訪問許可權為private,struct為public(因為struct要相容C)

注意:訪問限定符只在編譯時有用,當資料對映到記憶體後,沒有任何訪問限定符上的

封裝

概念:封裝:將資料和操作資料的方法進行有機結合,隱藏物件的屬性和實現細節,僅對外公開介面來和物件進行互動

C++實現封裝的方式:用類將物件的屬性與方法結合在一塊,讓物件更加完善,通過訪問許可權選擇性的將其介面提供給外部的使用者使用

封裝本質上是一種管理:我們如何管理兵馬俑呢?比如如果什麼都不管,兵馬俑就被隨意破壞了。那麼我們首先建了一座房子把兵馬俑給封裝起來。但是我們目的全封裝起來,不讓別人看。所以我們開放了售票通道,可以買票突破封裝在合理的監管機制下進去參觀。類也是一樣,我們使用類資料和方法都封裝到一下。不想給別人看到的,我們使用protected/private把成員封裝起來。開放一些共有的成員函式對成員合理的訪問。所以封裝本質是一種管理。

類的作用域

類定義了一個新的作用域,類的所有成員都在類的作用域中。在類體外定義成員,需要使用 :: 作用域解析符
指明成員屬於哪個類域。作用域外,藉助成員訪問操作符.和->來訪問類成員。

類的例項化

概念:用類型別建立物件的過程,稱為類的實

特性:1. 類只是一個模型一樣的東西,限定了類有哪些成員,定義出一個類並沒有分配實際的記憶體空間來存。2. 一個類可以例項化出多個物件,例項化出的物件 佔用實際的物理空間,儲存類成員。

例子:打個比方。類例項化出物件就像現實中使用建築設計圖建造出房子,類就像是設計圖,只設計出需要什麼東西,但是並沒有實體的建築存在,同樣類也只是一個設計,例項化出的物件才能實際儲存資料,佔用物理空間。

類物件大小計算

儲存方式猜測

1.物件中包含類的各個成員:

缺陷:每個物件中成員變數是不同的,但是呼叫同一份函式,如果按照此種方式儲存,當一個類建立多
個物件時,每個物件中都會儲存一份程式碼,相同程式碼儲存多次,浪費空間。那麼如何解決呢?

2.只儲存成員變數,成員函式存放在公共的程式碼段:

類物件大小計算規則

一個類的大小,實際就是該類中”成員變數”之和,當然也要進行記憶體對齊,注意空類的大小,空類比
較特殊,編譯器給了空類一個位元組來唯一標識這個類。

結構體記憶體對齊

1. 第一個成員在與結構體偏移量為0的地址處。
2. 其他成員變數要對齊到某個數字(對齊數)的整數倍的地址處。注意:對齊數 = 編譯器預設的一個對齊數 與 該成員大小的較小值。VS中預設的對齊數為8,gcc中的對齊數為4
3. 結構體總大小為:最大對齊數(所有變數型別最大者與預設對齊引數取最小)的整數倍。
4. 如果嵌套了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是
所有最大對齊數(含巢狀結構體的對齊數)的整數倍。

this指標

引出

我們先來定義一個日期類Da

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兩個成員函式,函式體中沒有關於不同物件的區分,那當s1呼叫SetDate函式時,該函式是如何知道應該設定s1物件,而不是設定s2物件呢?
C++中通過引入this指標解決該問題,即:C++編譯器給每個“成員函式“增加了一個隱藏的指標引數,讓該指標指向當前物件(函式執行時呼叫該函式的物件),在函式體中所有成員變數的操作,都是通過該指標去訪問。只不過所有的操作對使用者是透明的,即使用者不需要來傳遞編譯器自動完成。

this指標特性

1. this指標的型別:類型別* const
2. 只能在“成員函式”的內部使用
3. this指標本質上其實是一個成員函式的形參,是物件呼叫成員函式時,將物件地址作為實參傳遞給this形參。所以物件中不儲存this指標。
4. this指標是成員函式第一個隱含的指標形參,一般情況由編譯器通過ecx暫存器自動傳遞,不需要使用者
傳遞。

this指標存在於棧上