c++11Primer(第七章)

類的簡介

最開始的時候我們用struct定義了一個數據結構

struct Sales_data{
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    };

c++11標準規定可以爲數據成員提供一個類內初始值。創建對象時,類內初始值用於初始化數據成員。沒有初始值的成員將被默認初始化。(默認初始化:對於內置類型,如果定義於任何函數之外則被初始化爲0,如果定義在函數體內部,則內置類型變量不被初始化。類的對象沒有顯示初始化,其值由類確定。)類內的初始值可以放在花括號裏,或者等號右邊,但是不能使用圓括號。

使用Sales_data類

可以像使用內置類型一樣定義這種類型的變量

Sales_data data1,data2;

我們的目的是讓Sales_data類支持的操作:
一個isbn成員函數
一個combine成員函數,用於將一個Sales_data對象與另一個Sales_data相加
一個add函數,執行兩個Sales_data對象的加法
一個read函數,將數據從istream讀入到Sales_data對象中
一個print函數,用於輸出Sales_data對象的值到ostream

std::string isbn() const {return bookNo;}

雖然這個函數很簡單,但是還是有些知識點的。首先這個函數定義在類的內部,也就是說這個函數默認是inline的。inline函數沒有函數調用的幀棧操作,因爲在編譯階段inline函數會被替換爲他的函數體。此函數聲明之後的const標明這個函數不會改變調用他的對象。

Sales_data& combine(const Sales_data&);

用引用得到方式傳值可以減少傳入值的拷貝操作,利用pass-by-const-reference來提高性能。如果我們返回的值是一個引用,那麼就可以不使用c++的return-by-value的這種機制,而變成return-by-reference。

std::ostream& print(std::ostream&,const Sales_data&);

IO對象是不能夠被copy的,所以使用pass-by-reference和return-by-reference來實現參數的傳遞和返回值的傳遞。

當我們在調用成員函數的時候:

total.isbn();

我們實際上是在替某個對象調用isbn()。如果isbn()指向Sales_data的某個成員,則它隱式的指向調用該函數的對象的成員。成員函數通過一個隱士的this指針來訪問調用它的那個對象。我們的this指針是一個常指針,也就是說他保存的地址是不會改變的。如果我們要讓this指針所指向的對象也是const的,那麼我們就要在成員函數的末尾加上const關鍵字。在這裏,this的類型是 Sales_data * const,也就是說,我們可以通過解引用this來更獲得這個對象,進而對其進行更改。所以this不能綁定在const對象上,因爲const對象返回的是 Sales_data const *。const對象,以及const對象的引用或指針都只能調用常量成員函數。

類的作用域

只需記住一句話:編譯器分兩步處理類:首先編譯成員的聲明,然後才輪到成員函數體。因此,成員函數體可以隨意使用類中的其他成員而無需在意這些成員出現的次序。

在類的外部定義成員函數

如果成員被聲明成常量成員函數,那麼它的定義也必須在參數列表後明確指定const屬性。同時,類外部定義的成員的名字必須包含它所屬的類名。

double Sales_data::avg_price() const {
    if(units_sold)
        return revenue/units_sold;
    else
        return 0;
}

函數名Sales_data::avg_price使用作用於操作符來說明如下的事實:我們定義了一個名爲avg_price的函數,並且該函數被聲明在類Sales_data的作用域內。一旦編譯器看到這個函數名,就能理解剩餘的代碼是位於類的作用於內的。

定義一個返回this對象的函數

return *this;

return語句解引用this指針以獲得執行該函數的對象。

構造函數

不同於其他成員函數,構造函數不能被聲明成const的。當我們創建類的一個const對象時,指導構造函數完成初始化過程,對象才能整整取得其“常量”屬性。因此,構造函數在const對象的構造過程中可以向其寫值。也就是說不管是const對象還是非const對象的創建過程,用到的構造函數是同一個。所以構造函數加不加const沒有任何影響,所以標準規定不能加const。

合成的默認構造函數

只有沒有定義任何一個構造函數時,編譯器纔會爲我們生成默認的構造函數。默認構造函數採取的初始化方式爲:如果存在類內的初始值,則用它來初始化成員,否則,默認初始化該成員。

某些類並不能依賴於默認的構造函數。比如數據成員有內置類型或者複合類型,合成的默認構造函數將會對這些數據成員進行默認初始化,而默認初始化得到的結果,可能就是未定義的值。另一種情況是,類中有沒有默認構造函數的成員,這樣在使用默認構造函數時,將會因爲該成員沒有默認構造函數而報錯。

=default的含義

我們希望這個函數的作用完全等同於之前使用的合成默認構造函數。

構造函數初始值列表

初始化順序和變量聲明的順序一致。

拷貝、賦值和析構

對象在集中情況下會被拷貝,如我們初始化變量以及以值的方式傳遞或返回一個對象等。當我們使用了賦值運算符時會發生對象的賦值操作。當對象不再存在時執行銷燬的操作,比如一個局部對象會在創建他的塊結束時被銷燬。

友元

類可以允許其他類或者函數訪問它的非公有成員,方法是令其他類或者函數成爲它的友元。
友元的聲明僅僅指定了訪問的權限,而非一個通常意義上的函數聲明。如果我們希望類的用戶能夠調用某個友元函數,那麼我們就必須在友元聲明之外再專門對函數進行一次聲明。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章