與C一樣,C++使用布爾表達(dá)式簡化求值法(short-circuit evaluation)。這表示一旦確定了布爾表達(dá)式的真假值,即使還有部分表達(dá)式?jīng)]有被測試,布爾表達(dá)式也停止運(yùn)算。例如:
char *p;
...
if ((p != 0) && (strlen(p) > 10)) ...
這里不用擔(dān)心當(dāng)p為空時strlen無法正確運(yùn)行,因?yàn)槿绻鹥不等于0的測試失敗,strlen不會被調(diào)用。同樣:
int rangeCheck(int index)
{
if ((index < lowerBound) || (index > upperBound)) ...
...
}
如果index小于lowerBound,它不會與upperBound進(jìn)行比較。
很早以前上述行為特性就被反復(fù)灌輸給C和C++的程序員,所以他們都知道該特性。而且他們也依賴于簡短求值法來寫程序。例如在上述第一個代碼中,當(dāng)p為空指針時確保strlen不會被調(diào)用是很重要的,因?yàn)镃++標(biāo)準(zhǔn)說(正如C標(biāo)準(zhǔn)所說)用空指針調(diào)用strlen,結(jié)果不確定。
C++允許根據(jù)用戶定義的類型,來定制&&和||操作符。方法是重載函數(shù)operator&& 和operator||,你能在全局重載或每個類里重載。然而如果你想使用這種方法,你必須知道你正在極大地改變游戲規(guī)則。因?yàn)槟阋院瘮?shù)調(diào)用法替代了簡短計(jì)算法。也就是說如果你重載了操作符&&,對于你來說代碼是這樣的:
if (expression1 && expression2) ...
對于編譯器來說,等同于下面代碼之一:
if (expression1.operator&&(expression2)) ...
// when operator&& is a
// member function
if (operator&&(expression1, expression2)) ...
// when operator&& is a
// global function
這好像沒有什么不同,但是函數(shù)調(diào)用法與簡短求值法是絕對不同的。首先當(dāng)函數(shù)被調(diào)用時,需要運(yùn)算其所有參數(shù),所以調(diào)用函數(shù)functions operator&& 和 operator||時,兩個參數(shù)都需要計(jì)算,換言之,沒有采用簡短計(jì)算法。第二是C++語言規(guī)范沒有定義函數(shù)參數(shù)的計(jì)算順序,所以沒有辦法知道表達(dá)式1與表達(dá)式2哪一個先計(jì)算。完全與具有從左參數(shù)到右參數(shù)計(jì)算順序的簡短計(jì)算法相反。
因此如果你重載&&或||,就沒有辦法提供給程序員他們所期望和使用的行為特性,所以不要重載&&和||。
同樣的理由也適用于括號操作符,但是在我們深入研究它之前,我還是暫停一下,讓你不要太驚訝,“逗號操作符?哪有逗號操作符?”確實(shí)存在。
char *p;
...
if ((p != 0) && (strlen(p) > 10)) ...
這里不用擔(dān)心當(dāng)p為空時strlen無法正確運(yùn)行,因?yàn)槿绻鹥不等于0的測試失敗,strlen不會被調(diào)用。同樣:
int rangeCheck(int index)
{
if ((index < lowerBound) || (index > upperBound)) ...
...
}
如果index小于lowerBound,它不會與upperBound進(jìn)行比較。
很早以前上述行為特性就被反復(fù)灌輸給C和C++的程序員,所以他們都知道該特性。而且他們也依賴于簡短求值法來寫程序。例如在上述第一個代碼中,當(dāng)p為空指針時確保strlen不會被調(diào)用是很重要的,因?yàn)镃++標(biāo)準(zhǔn)說(正如C標(biāo)準(zhǔn)所說)用空指針調(diào)用strlen,結(jié)果不確定。
C++允許根據(jù)用戶定義的類型,來定制&&和||操作符。方法是重載函數(shù)operator&& 和operator||,你能在全局重載或每個類里重載。然而如果你想使用這種方法,你必須知道你正在極大地改變游戲規(guī)則。因?yàn)槟阋院瘮?shù)調(diào)用法替代了簡短計(jì)算法。也就是說如果你重載了操作符&&,對于你來說代碼是這樣的:
if (expression1 && expression2) ...
對于編譯器來說,等同于下面代碼之一:
if (expression1.operator&&(expression2)) ...
// when operator&& is a
// member function
if (operator&&(expression1, expression2)) ...
// when operator&& is a
// global function
這好像沒有什么不同,但是函數(shù)調(diào)用法與簡短求值法是絕對不同的。首先當(dāng)函數(shù)被調(diào)用時,需要運(yùn)算其所有參數(shù),所以調(diào)用函數(shù)functions operator&& 和 operator||時,兩個參數(shù)都需要計(jì)算,換言之,沒有采用簡短計(jì)算法。第二是C++語言規(guī)范沒有定義函數(shù)參數(shù)的計(jì)算順序,所以沒有辦法知道表達(dá)式1與表達(dá)式2哪一個先計(jì)算。完全與具有從左參數(shù)到右參數(shù)計(jì)算順序的簡短計(jì)算法相反。
因此如果你重載&&或||,就沒有辦法提供給程序員他們所期望和使用的行為特性,所以不要重載&&和||。
同樣的理由也適用于括號操作符,但是在我們深入研究它之前,我還是暫停一下,讓你不要太驚訝,“逗號操作符?哪有逗號操作符?”確實(shí)存在。