国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

More Effective C++:不要重載的操作符

2019-11-17 05:34:31
字體:
供稿:網(wǎng)友

  與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為空時(shí)strlen無法正確運(yùn)行,因?yàn)榧偃鏿不等于0的測試失敗,strlen不會(huì)被調(diào)用。同樣:

int rangeCheck(int index)
{
 if ((index < lowerBound) (index > upperBound)) ...
  ...
}
  假如index小于lowerBound,它不會(huì)與upperBound進(jìn)行比較。
 
  很早以前上述行為特性就被反復(fù)灌輸給C和C++的程序員,所以他們都知道該特性。而且他們也依靠于簡短求值法來寫程序。例如在上述第一個(gè)代碼中,當(dāng)p為空指針時(shí)確保strlen不會(huì)被調(diào)用是很重要的,因?yàn)镃++標(biāo)準(zhǔn)說(正如C標(biāo)準(zhǔn)所說)用空指針調(diào)用strlen,結(jié)果不確定。

  C++答應(yīng)根據(jù)用戶定義的類型,來定制&&和操作符。方法是重載函數(shù)Operator&& 和operator,你能在全局重載或每個(gè)類里重載。然而假如你想使用這種方法,你必須知道你正在極大地改變游戲規(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)用時(shí),需要運(yùn)算其所有參數(shù),所以調(diào)用函數(shù)functions operator&& 和 operator時(shí),兩個(gè)參數(shù)都需要計(jì)算,換言之,沒有采用簡短計(jì)算法。第二是C++語言規(guī)范沒有定義函數(shù)參數(shù)的計(jì)算順序,所以沒有辦法知道表達(dá)式1與表達(dá)式2哪一個(gè)先計(jì)算。完全與具有從左參數(shù)到右參數(shù)計(jì)算順序的簡短計(jì)算法相反。

  因此假如你重載&&或,就沒有辦法提供給程序員他們所期望和使用的行為特性,所以不要重載&&和。

  同樣的理由也適用于括號(hào)操作符,但是在我們深入研究它之前,我還是暫停一下,讓你不要太驚奇,“逗號(hào)操作符?哪有逗號(hào)操作符?”確實(shí)存在。

  逗號(hào)操作符用于組成表達(dá)式,你經(jīng)常在for循環(huán)的更新部分(update part)里遇見它。例如下面來源于Kernighan's and Ritchie's 經(jīng)典書籍The C Programming Language 第二版(Prentice-Hall, 1988)的函數(shù):

// reverse string s in place

void reverse(char s[])
{
 for (int i = 0, j = strlen(s)-1;i < j;++i, --j) // 啊! 逗號(hào)操作符!
 {
  int c = s[i];
  s[i] = s[j];
  s[j] = c;
 }
}
  在for循環(huán)的最后一個(gè)部分里,i被增加同時(shí)j被減少。在這里使用逗號(hào)很方便,因?yàn)樵谧詈笠粋€(gè)部分里只能使用一個(gè)表達(dá)式,分開表達(dá)式來改變i和j的值是不合法的。

  對于內(nèi)建類型&&和,C++有一些規(guī)則來定義它們?nèi)绾芜\(yùn)算。與此相同,也有規(guī)則來定義逗號(hào)操作符的計(jì)算方法。一個(gè)包含逗號(hào)的表達(dá)式首先計(jì)算逗號(hào)左邊的表達(dá)式,然后計(jì)算逗號(hào)右邊的表達(dá)式;整個(gè)表達(dá)式的結(jié)果是逗號(hào)右邊表達(dá)式的值。所以在上述循環(huán)的最后部分里,編譯器首先計(jì)算++i,然后是—j,逗號(hào)表達(dá)式的結(jié)果是--j。

  也許你想為什么你需要知道這些內(nèi)容呢?因?yàn)槟阈枰M這個(gè)行為特性,假如你想大膽地寫自己的逗號(hào)操作符函數(shù)。不幸的是你無法模擬。

  假如你寫一個(gè)非成員函數(shù)operator,你不能保證左邊的表達(dá)式先于右邊的表達(dá)式計(jì)算,因?yàn)楹瘮?shù)(operator)調(diào)用時(shí)兩個(gè)表達(dá)式做為參數(shù)被傳遞出去。但是你不能控制函數(shù)參數(shù)的計(jì)算順序。所以非成員函數(shù)的方法絕對不行。

  剩下的只有寫成員函數(shù)operator的可能性了。即使這里你也不能依靠于逗號(hào)左邊表達(dá)式先被計(jì)算的行為特性,因?yàn)榫幾g器不一定必須按此方法去計(jì)算。因此你不能重載逗號(hào)操作符,保證它的行為特性與其被料想的一樣。重載它是完全輕率的行為。

  你可能正在想這個(gè)重載惡夢究竟有沒有完。究竟假如你能重載逗號(hào)操作符,你還有什么不能重載的呢?正如顯示的,存在一些限制,你不能重載下面的操作符:

. .* :: ?:

new delete sizeof typeid

static_cast dynamic_cast const_cast reinterpret_cast
  你能重載:

operator new operator delete

operator new[] operator delete[]

+ - * / % ^ & ~

! = < > += -= *= /= %=

^= &= = << >> >>= <<= == !=

<= >= && ++ -- , ->* ->

() []
  當(dāng)然能重載這些操作符不是去重載的理由。操作符重載的目的是使程序更輕易閱讀,書寫和理解,而不是用你的知識(shí)去迷惑其他人。假如你沒有一個(gè)好理由重載操作符,就不要重載。在碰到&&, , 和 ,時(shí),找到一個(gè)好理由是困難的,因?yàn)闊o論你怎么努力,也不能讓它們的行為特性與所期望的一樣。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 益阳市| 泾川县| 喀喇| 巫山县| 甘谷县| 绥滨县| 宁晋县| 梅河口市| 鄯善县| 视频| 弥勒县| 梧州市| 庆阳市| 马龙县| 玛纳斯县| 尖扎县| 姚安县| 广东省| 惠安县| 门头沟区| 肇庆市| 嘉禾县| 黄陵县| 武威市| 北辰区| 黄冈市| 昭觉县| 隆林| 灌南县| 邵阳市| 同仁县| 得荣县| 开江县| 临武县| 兴国县| 禹城市| 柳河县| 察雅县| 文安县| 浏阳市| 大邑县|