?
這里初看到”class”和”type”,感覺他們是說的是同一樣東西,但仔細讀了一下,兩者在文中還是有區別的。class側重于自定義的類,而type側重于系統預定義的類(像int、double、string、vector)。設計好的class,使之像設計type一樣,就是說要使自己設計的類像系統預定義的類那樣好用,這對設計思想提出了較高的要求。
要設計高效的class,需要回答以下的問題:
1. 對象如何去創建和銷毀?
這是構造函數和析構函數的問題,當然如果想要有堆分配方式,還需要重載new、new[]、delete和delete[]運算符;
?
2. 對象初始化與對象的賦值應該有什么樣的差別?
初始化是構造函數和拷貝構造函數的事(這時候對象還沒有產生),但對象的賦值卻不同,因為此時等號左邊的對象已經存在了。
?
3. 新type如果被pass-by-value意味著什么?
會調用相應的拷貝構造函數,要注意是否需要一個深拷貝。
?
4. 什么是新type的合法值?
要對對象的合法值進行限定,通常在構造函數中就對成員變量的范圍給出限定,警惕不安全的輸入值!
?
5. 你的新type需要配合某個繼承圖系嗎?
就是判斷自己設計的class是否需要繼承或被繼承,是基類還是派生類。如果是基類的話,要注意是否允許這個基類生成對象(是否需要利用純虛函數設計成抽象類),以及要將析構函數前面加上virtual。
?
6. 新type需要什么樣的轉換?
主要是針對隱式轉換,operator OtherType() const,但通常情況下隱式轉換也意味著隱患,所以設計時要謹慎。另外,構造函數中也要當心,如果不想讓隱式構造發生,就要在前面加上explicit關鍵字。舉個例子:
1 class A 2 3 { 4 5 private: 6 7 int a; 8 9 public: 10 11 A(int b):a(b){} 12 13 }; 14 15 void fun(A obj);
若調用fun(3),則編譯器也能接受,因為編譯器自動作了fun(A(3))的處理,這就是隱式構造。而如果用戶自己寫fun(A(3)),這是顯式構造。當A的構造函數前有explicit時,fun(3)的調用將通不過編譯器。通常情況下,隱式轉換是安全的。
?
7. 什么樣的操作符和函數對此新type而言是合理的?
就是設計什么樣的成員函數,以及重載哪些運算符。
?
8. 什么樣的標準函數應該駁回?
是說哪些函數對外公開,哪些函數對內使用,這就是private,public和protected的功能啦,protected只有在有繼承關系的類中使用才能發揮它真正的力量,普通的類用private和public就足夠了。
?
9. 誰該取用新type成員?
與上面一條類似,就是類的封裝性問題,一些而言,成員變量都應該是private的,而在public函數里面提供對這些成員變量的訪問get和set函數。如果需要的話,可以使用友元,但友元也要慎用,因為有些編譯器對之支持的不是很好,另一方面,友元成為破壞封裝性的特例,會帶來安全的隱患。
?
10. 什么是新type的未聲明接口?
這個不大明白意思,先放在這里……
?
11. 你的新type有多么一般化?
這牽涉到泛型編程了,就是模板的概念,這是C++比C要方便的多的多的地方——它將需要的類型交給編譯器自動生成。
?
12. 你真的需要一個新type嗎?
其實我覺得應該把這個問題放在第一個,因為設計最初首先要問的就是這個問題,如果都沒有必要設計了,還需要回答前十一個問題嗎?
?
最后總結一下:
class的設計就是type的設計,在設計之前先要把上述12個問題過一遍,這樣可以有把握設計一個成功的類。