namespace std
{
template<class T>
void swap(T&a,T&b)
{
T temp(a);
a=b;
b=temp;
}
}
//T支援copying函數即可。
//pimpl手法:以指標指向一個對象,內含真正資料。
//在namespace std中只能全特化,不能偏特化,
//如
namspace std
{
template<> void swap<A>(A&a,A&b)
{
.....
}
}
介面:使用者和代碼的互動。
用戶端錯誤可以匯入新類型而防止使用者錯誤。
接下來是Date的執行個體,面對匯入新類型。
class Date<br />{<br /> public:<br /> Date(int month,int day,int year); //壞處就是對於month,day,year大小沒有約束。<br /> ...<br />};<br />struct Day<br />{<br /> explicit Day(int d):val(d){}<br /> int val;<br />};<br />struct Month<br />{<br /> explicit Month(int m):val(m){} //支援顯式而不支援隱式轉換是因為防止不正確的實參。<br /> int val;<br />};<br />struct Year<br />{<br /> explicit Year(int y):val(y){}<br /> int val;<br />};</p><p>class Date{<br /> public:<br /> Date(const Month& m,const Day& d,const Year& y);<br />};<br />
對於資料範圍,我們做了進一步的編程。更改如下:
class Month<br />{<br /> private:<br /> explicit Month(int m):val(m){} //支援顯式而不支援隱式轉換是因為防止不正確的實參。<br /> public:<br /> static Month Jan(){return Month(1);}<br /> static Month Feb(){return Month(2);}<br /> static Month Mar(){return Month(3);}<br /> ...<br /> static Month Dec(){return Month(12);}</p><p>};<br />Date d(Month::Mar(),Day(20),Year(1995));
盡量讓自訂類型的行為與內建類型一致。
勤快的使用shared_ptr,因為他能防止客戶犯下資源泄漏的錯誤。
但是shared_ptr是原始指標的兩倍大,但是額外成本不顯著。
下面講一下設計class的設計規範:
1.注意對象的建立和銷毀過程。
2.搞清對象初始化和賦值的區別。
3.class 的pass-by-value的意義(調用copy函數)
4.注意此類是否是基類或不是。
5.需要什麼類型轉換。
6.誰該取用新type成員。
7.建構函式的explicit。
8.看看是否一般化。
在類中成員函數的參數傳遞時,多用pass-by-reference-const而不用pass-by-value
因為1.速度快。2.能夠類型轉換(繼承)
適合pass-by-value的類型:1.內建。2.STL迭代器和函數對象。
對於返回對象的非成員函數,不能亂用reference。
成員變數設為private。
改變共有成員變數會破壞客戶代碼。
用non-member和non-friend替換member,因為更好的封裝。
愈多函數可訪問他,資料封裝性就愈低。
用namespace將類與便利函數封裝,可以更好的布局。而且namespace可以隨時添加函數。
若所有參數需要轉換類型,採用non-member。
class Rational<br />{<br />public:<br />Rational(int numerator=0,int denominator=1);<br />int numerator() const;<br />int denominator() const;<br />const Rational operator*(const Rational& rhs) const;//左邊不能類型轉換。<br />private:<br />...<br />};<br />const Rational operator*(const Rational&lhs,const Rational& rhs);//適合所有類型轉換。
swap()
namespace std<br />{<br />template<class T><br />void swap(T&a,T&b)<br />{<br />T temp(a);<br />a=b;<br />b=temp;<br />}<br />}<br />//T支援copying函數即可。<br />//pimpl手法:以指標指向一個對象,內含真正資料。<br />//在namespace std中只能全特化,不能偏特化,<br />//如<br />namspace std<br />{<br />template<> void swap<A>(A&a,A&b)<br />{<br />.....<br />}<br />}<br />
一般來說要用swap可以在class裡聲明一個swap成員函數,這樣可以在swap成員函數中調用stl中的swap函數。
然後再到std中寫下特化版本。
C++只能對class偏特化,而不能對function偏特化。
如果想調用std中swap,可以用using std::swap,意思是先看特化版本,再看一般模板版本。
本來的swap不能滿足要求的原因是因為class中的pimpl手法:
解決步驟:
1.先public swap成員函數。
2.在class所在的namespace中提供一個non-member swap
3.當你調用swap時確定包含using聲明式。