從你開始做C程序員那天開始,你就記住increment的前綴形式有時叫做“增加然后取回”,后綴形式叫做“取回然后增加”。這兩句話非常重要,因為它們是increment前綴與后綴的形式上的規(guī)范。
// 前綴形式:增加然后取回值
UPInt& UPInt::operator++()
{
*this += 1; // 增加
return *this; // 取回值
}
// postfix form: fetch and increment
const UPInt UPInt::operator++(int)
{
UPInt oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}
后綴操作符函數(shù)沒有使用它的參數(shù)。它的參數(shù)只是用來區(qū)分前綴與后綴函數(shù)調(diào)用。如果你沒有在函數(shù)里使用參數(shù),許多編譯器會顯示警告信息,很令人討厭。為了避免這些警告信息,一種經(jīng)常使用的方法時省略掉你不想使用的參數(shù)名稱;如上所示。
很明顯一個后綴increment必須返回一個對象(它返回的是增加前的值),但是為什么是const對象呢?假設(shè)不是const對象,下面的代碼就是正確的:
UPInt i;
i++++; // 兩次increment后綴
// 運算
這組代碼與下面的代碼相同:
i.operator++(0).operator++(0);
很明顯,第一個調(diào)用的operator++函數(shù)返回的對象調(diào)用了第二個operator++函數(shù)。
有兩個理由導(dǎo)致我們應(yīng)該厭惡上述這種做法,第一是與內(nèi)置類型行為不一致。當(dāng)設(shè)計一個類遇到問題時,一個好的準(zhǔn)則是使該類的行為與int類型一致。而int類型不允許連續(xù)進(jìn)行兩次后綴increment:
int i;
i++++; // 錯誤!
第二個原因是使用兩次后綴increment所產(chǎn)生的結(jié)果與調(diào)用者期望的不一致。如上所示,第二次 調(diào)用operator++改變的值是第一次調(diào)用返回對象的值,而不是原始對象的值。因此如果:
i++++;
是合法的,i將僅僅增加了一次。這與人的直覺相違背,使人迷惑(對于int類型和UPInt都是一樣),所以最好禁止這么做。
C++禁止int類型這么做,同時你也必須禁止你自己寫的類有這樣的行為。最容易的方法是讓后綴increment 返回const對象。當(dāng)編譯器遇到這樣的代碼:
i++++; // same as i.operator++(0).operator++(0);
它發(fā)現(xiàn)從第一個operator++函數(shù)返回的const對象又調(diào)用operator++函數(shù),然而這個函數(shù)是一個non-const成員函數(shù),所以const對象不能調(diào)用這個函數(shù)。如果你原來想過讓一個函數(shù)返回const對象沒有任何意義,現(xiàn)在你就知道有時還是有用的,后綴increment和decrement就是例子。(更多的例子參見Effective C++ 條款21)
如果你很關(guān)心效率問題,當(dāng)你第一次看到后綴increment函數(shù)時, 你可能覺得有些問題。這個函數(shù)必須建立一個臨時對象以做為它的返回值,(參見條款19),上述實現(xiàn)代碼建立了一個顯示的臨時對象(oldValue),這個臨時對象必須被構(gòu)造并在最后被結(jié)構(gòu)。前綴increment函數(shù)沒有這樣的臨時對象。由此得出一個令人驚訝的結(jié)論,如果僅為了提高代碼效率,UPInt的調(diào)用者應(yīng)該盡量使用前綴increment,少用后綴increment,除非確實需要使用后綴increment。讓我們明確一下,當(dāng)處理用戶定義的類型時,盡可能地使用前綴increment,因為它的效率較高。
我們再觀察一下后綴與前綴increment 操作符。它們除了返回值不同外,所完成的功能是一樣的,即值加一。簡而言之,它們被認(rèn)為功能一樣。那么你如何確保后綴increment和前綴increment的行為一致呢?當(dāng)不同的程序員去維護(hù)和升級代碼時,有什么能保證它們不會產(chǎn)生差異?除非你遵守上述代碼里的原則,這才能得到確保。這個原則是后綴increment和decrement應(yīng)該根據(jù)它們的前綴形式來實現(xiàn)。你僅僅需要維護(hù)前綴版本,因為后綴形式自動與前綴形式的行為一致。
正如你所看到的,掌握前綴和后綴increment和decrement是容易的。一旦了解了他們正確的返回值類型以及后綴操作符應(yīng)該以前綴操作符為基礎(chǔ)來實現(xiàn)的規(guī)則,就足夠了。