1.Conversion Function
基本類型之間可以互相轉換,那么類類型呢?看下面代碼
輸出結果是4.6
在運算 4 + f 時有兩條路:
(1)編譯器會去找有沒有一個叫 operator + 的函數(這里只給出類內的例子)
(2)如果沒有就去找一個叫 operator double 的函數
轉換函數的語法: operator 類型()
在這個例子中只有operator double()所以編譯器會先調用他把 f 轉換成 0.6 然后加上 4。
在類中可以寫多個轉換函數,只要覺得有必要,在需要轉換的場合編譯器會自己去調用相應的轉換函數(和隱式類型轉換很像,當然也可以強轉)。
2.non-explicit-one-argument ctor
當執行到 f + 4 時,會調用operator + 這個函數,然而 4 是一個整數不是Fraction類(operator +的參數是const Fraction& m),那么4要怎么加到 f 上去呢?
看一下構造函數:
這個構造函數他有兩個參數,其中一個是有默認值的,另外一個需要自己傳遞參數,這種只需要傳遞一個參數的構造函數被叫做單參構造。
當執行 f + 4 時,會先調用單參構造函數,將4變成一個Fraction(4,1)對象(在臨時區里),然后在調用operator + 。
單參構造函數可以把別的東西轉換成對應的類型(只要可以轉換)。
2.1Conversion Function vs non-explicit-one-argument ctor
當轉換函數和單參構造并存的時候就會發生error
這是因為編譯器有兩條路完成 d2 = f + 4
(1)調用單參構造,將4轉換成Fraction對象,然后調用operator +,完成計算。
(2)調用operator double ,將 f 轉換成double類型加上4,再調用單參構造轉換成Fraction對象,最后賦值。
這時編譯器無法自動選擇哪一條路,需要在單參構造函數前面加上explicit
2.2Explicit-one-argument ctor
加上explicit后,編譯出現新的error
編譯器說:無法將double類型轉換成Fraction類型
這是因為,先調用了operator double 將 f 轉換成double,然后加上4,這時原本需要使用單參構造把結果轉成Fraction類型,但是由于explicit,單參構造不能被調用,所以報錯:無法將double類型轉換成Fraction類型。
explicit關鍵字:在編譯有歧義的時候,起到禁止編譯器自動調用的功能。
這個關鍵字一般只在以上這種情況下加在構造函數前。
3.pointer-like classe
一個C++的class可能會像一個指針(面向指針),為什么要把一個class設計的像一個指針呢,因為我們希望這個class對象能比普通的指針多做一些事情(這是一個聰明的指針)
在上面的代碼中,通過重載 * 和 -> 這兩個操作符讓類可以像指針一樣使用的能力
智能指針中 * 的操作符重載無一例外,都是如上述代碼這樣寫,因為想要和對指針解引用,必需返回的是*px(取px指向的地址的內容)。
ptr->print(); 通過重載解釋,->與ptr作用,然后返回的是px(指向內容的地址),然->應該沒有了呀(操作符使用掉了),那為什么相當于px->print(),為什么->還留在那里,這是因為->符號只要在那里,他的作用會一直保持著,不會被消耗掉。->的寫法也是固定的。
4.Function-like classes
函數名后面都有一個()操作符,這個()操作符的名字叫 函數調用操作符,將()重載之后,類對象就能像函數一樣使用。
5.member template
成員模板語法:
在類中,下面的構造
是類中的一個成員,這個成員自己本身又是一個模板,我們就把這種成員叫為 成員模板。
使用:
在泛型編程中,在構造函數,拷貝構造這類函數上面會大量用到成員模板,用來增加函數的通用性。
在智能指針中也有應用:
6.specializtion
設計一個泛型的Compare類用來比較不同數據類型之間的大小:
這個例子只是比較了整數之間的大小,如果我們想用來比較浮點數之間的大小,那么這個例子就不可行了,因為浮點數在計算機中不能精確的比較,只能指定一個差值范圍進行比較。
那么就需要對泛型類進行特化處理:
有時為了需要,針對特定的類型,需要對模板進行特化,這其實就是特殊處理。
7.template template parameter
注意:
class Sequence = deque不是模板模板參數,因為在指定模板參數時,Sequence的值已經指定好了,這個模板指定了T后就沒有了灰色的,未確定的東西。
真正的模板模板參數需要手動指定