天天看點

類與對象 中類與對象(中)

類與對象(中)

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;
};
           
  1. 聲明放在.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++實作封裝的方式:用類将對象的屬性與方法結合在一塊,讓對象更加完善,通過通路權限選擇性的将其接口提供給外部的使用者使用。

類與對象 中類與對象(中)

【通路限定符說明】

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

    注意:通路限定符隻在編譯時有用,當資料映射到記憶體後,沒有任何通路限定符上的差別

    C++中struct和class的差別?

    C++需要相容C語言,是以C++中struct可以當成結構體去使用。另外C++中struct還可以用來定義類,和class是定義類是一樣的,差別是struct的成員預設通路方式是public,class是struct的成員預設通路方式是private。

4.2封裝

面向對象的三大特性:封裝、繼承、多态。

封裝:将資料和操作資料的方法進行有機結合,隐藏對象的屬性和實作細節,僅對外公開接口來和對象進行互動。

5.類的執行個體化

用類類型建立對象的過程,稱為類的執行個體化

  1. 類隻是一個模型一樣的東西,限定了類有哪些成員,定義出一個類并沒有配置設定實際的記憶體空間來存儲它
  2. 一個類可以執行個體化出多個對象,執行個體化出的對象占用實際的實體空間,存儲類成員變量
  3. **類執行個體化出對象就像現實中使用建築設計圖建造出房子,類就像是設計圖,**隻設計出需要什麼東西,但是并沒有實體的建築存在,同樣類也隻是一個設計,執行個體化出的對象才能實際存儲資料,占用實體空間

    一個類相當于一份圖紙,一份圖紙可以建造多個建築,一個類可以執行個體化多個對象

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 結構體記憶體對齊規則

  1. 第一個成員在與結構體偏移量為0的位址處。
  2. 其他成員變量要對齊到某個數字(對齊數)的整數倍的位址處。

    注意:對齊數 = 編譯器預設的一個對齊數 與 該成員大小的較小值。VS中預設的對齊數為8

  3. 結構體總大小為:最大對齊數(所有變量類型最大者與預設對齊參數取最小)的整數倍。
  4. 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

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指針的特性

  1. this指針的類型:類 類型* const
  2. 隻能在“成員函數”的内部使用
  3. this指針本質上其實是一個成員函數的形參,是對象調用成員函數時,将對象位址作為實參傳遞給this形參。是以對象中不存儲this指針。
  4. this指針是成員函數第一個隐含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要使用者傳遞
void Display()
{
cout<<_year<<endl;
}
           
void Display(Date*this)
{
cout<<this->_year<<endl;
}
           

繼續閱讀