天天看點

C++之類和對象(一)(一)面向對象程式設計介紹(二)類的封裝(四)深拷貝與淺拷貝(五)對象初始化清單:(六)構造函數與析構函數調用的順序:

(一)面向對象程式設計介紹

1什麼是面向對象:

面向對象将系統看成通過互動作用用來完成特定功能對象的集合,每個對象用自己的方法來管理資料,也就是說隻有對象内部的代碼能夠操作對象内部的資料。

2面向過程的缺點:

不容易維護,靈活性差,不容易擴充,更談不上複用,由于客戶的需求多變,導緻程式員加班加點,甚至整個項目經常返工。

3面向對象的優點:

通過,繼承、封裝、多态降低程式的耦合度,并結合設計模式讓程式更容易修改和擴充,并且易于複用。易維護,品質高,效率高,易擴充

但缺點就是運作效率會下降百分之十左右

4.面向對象的特點:

1)抽象性:抽象是人們認識事物的一種方法,抓住事物本質,而不是内部具體實作的操作與步驟

2)封裝性:1°封裝是指按照資訊屏蔽的原則,把對象的屬性與方法(操作)放在一起,構成一個獨立的對象

                  2°通過限制對屬性的操作和通路權限,可以将資訊隐藏在對象内部,對外提供一定的接口,在對象之外隻能通過這個接口對對象進行操作

                  3°封裝性增加了對象的獨立性,進而保證了資料的可靠性

                  4°外部對象不能直接操作對象的屬性,隻能使用對象提供的服務

3)繼承性:1°繼承表達了對象的一般與特殊關系,特殊類的對象具有一般類的全部屬性和服務

                  2°當定義了一個類後,又定義的一個新類,這些新類與原來的類相比,隻是增加或修改了部分屬性與操作,這時可以用原來的類派生出一個新類,新類中隻描  述自己所特有的屬性與操作即可。

                  3°繼承性大大簡化了對問題的描述,大大提高了程式的可重用性,進而提高了程式設計,修改,擴充的效率。

4)多态:   1°同一個消息被不同對象接收時,産生不同結果,即實作同一接口,不同方法

                  2°一般類中定義的屬性與服務,在特殊類中不改變其名字,但通過各自不同的實作後,可以具有不同的資料類型或具有不同的行為

(二)類的封裝

1成員變量,C++中用于表示類屬性的變量

2成員函數,C++中用于表示類行為的函數

3 C++中提供一個新的關鍵字 class, 用來定義類,使用方式和struct基本相同

4   類的通路控制關鍵字:對屬性和方法的使用權限進行限制

    1° public  : 可以在類的内部和類的外部通路

    2° private : 可以在類的内部但不能在類的外部通路,沒有權限修飾的成員和函數預設是private的

    3°protect :可以在類的内部通路,但不能在類的外部通路,用在繼承裡面

5   在用struct定義類時,所有成員的預設屬性為public

     在用class定義類時,所有成員的預設屬性為private

6. 類的聲明與類的實作分開:類的聲明放在頭檔案中,類的實作放在源檔案中,使用去主函數調用即可

(三)對象的構造與析構

1.構造函數的定義:

1)C++中的類可以定義與類名相同的特殊成員函數,這種與類名相同的成員函數叫做構造函數;

2)構造函數在定義時可以有參數;

3)沒有任何傳回類型的聲明。

2.析構函數的定義:

1)C++中的類可以定義一個特殊的成員函數清理對象,這個特殊的成員函數叫做析構函數  文法:~ClassName()

2)析構函數沒有參數也沒有任何傳回類型的聲明

3)析構函數在對象銷毀時自動被調用

3.對象的構造與析構

1)拷貝構造函數的調用時機:

     1°Test t2 = t1;   // 用對象 t1 去初始化t2

     2°Test t2(t0);    // 用對象 t0 去初始化t2

     3°PrintObj(t0);   // 做函數參數的時候,實參到形參的轉換會調用拷貝構造函數

     4°t1 = test();       // 函數傳回值傳回對象, 用匿名對象給其他對象進行指派,複制完對象後匿名對象會被析構

2)預設構造函數:(二個特殊的構造函數)

1°預設無參構造函數

當類中沒有定義構造函數時,編譯器預設提供一個無參構造函數,并且其函數體為空

2°預設拷貝構造函數  

當類中沒有定義拷貝構造函數時,編譯器預設提供一個預設拷貝構造函數,簡單的進行成員變量的值複制

3)構造函數規則:

     1° 當類中沒有定義任何一個構造函數時,c++編譯器會提供預設無參構造函數和預設拷貝構造函數

     2° 當類中定義了拷貝構造函數時,c++編譯器不會提供無參數構造函數

     3° 當類中定義了任意的非拷貝構造函數(即:當類中提供了有參構造函數或無參構造函數),c++編譯器不會提供預設無參構造函數

     4° 預設拷貝構造函數成員變量簡單指派

總結:隻要你寫了構造函數,那麼你必須用。

4)構造析構階段性總結 

     1° 構造函數是C++中用于初始化對象狀态的特殊函數

     2° 構造函數在對象建立時自動被調用

     3° 構造函數和普通成員函數都遵循重載規則

     4° 拷貝構造函數是對象正确初始化的重要保證

     5° 必要的時候,必須手工編寫拷貝構造函數 

(四)深拷貝與淺拷貝

1淺拷貝存在的問題:

1°預設複制構造函數可以完成對象的資料成員值簡單的複制

2°對象的資料資源是由指針訓示的堆時,預設複制構造函數僅作指針值複制

2解決淺拷貝的方法:

深拷貝,自己寫一個拷貝構造函數,重新再堆上在配置設定一個空間,即可。例如請看如下代碼:

#include 
  
   
#include 
   
    
 
using namespace std;
 
class Name
{
public:
    Name(const char *p)
    {
        m_len = strlen(p);
        m_p = (char *)malloc(m_len + 1);
    }
 
    // 解決淺拷貝的方案:手動編寫拷貝構造函數,進行深拷貝
    Name (const Name &obj)
    {
        m_len = obj.m_len;
        m_p = (char *)malloc(m_len + 1);
        strcpy (m_p, obj.m_p);
    }
 
    ~Name()
    {
        cout << "析構函數被調用" << endl;
        if (m_p != NULL)
        {
            free (m_p);
            m_p = NULL;
            m_len = 0;
        }
        cout << "析構函數執行結束" << endl;
    }
private:
    char *m_p;
    int m_len;
};
 
int main()
{
    {
        Name name1("xiaoming");
        Name name2 = name1;
    }
 
    return 0;
}
   
  
           

(五)對象初始化清單:

1°初始化清單解決了一個類對象在其他類中無法初始化的問題

2°類成員中若有const修飾,必須在對象初始化的時候,給const int m 指派

當類成員中含有一個const對象時,或者是一個引用時,他們也必須要通過成員初始化清單進行初始化,

因為這兩種對象要在聲明後馬上初始化,而在構造函數中,做的是對他們的指派,這樣是不被允許的。

3°C++中提供初始化清單對成員變量進行初始化

文法規則

Constructor::Contructor() : m1(v1), m2(v1,v2), m3(v3)

{

    // some other assignment operation

}

4°注意概念

初始化:被初始化的對象正在建立

指派:被指派的對象已經存在

5°注意:

成員變量的初始化順序與聲明的順序相關,與在初始化清單中的順序無關

初始化清單先于構造函數的函數體執行

(六)構造函數與析構函數調用的順序:

1°當類中有成員變量是其它類的對象時,首先調用成員變量的構造函數,調用順序與聲明順序相同;之後調用自身類的構造函數

2°析構函數的調用順序與對應的構造函數調用順序相反

c++

繼續閱讀