Re: [問題] return問題

作者: Schottky (順風相送)   2016-04-28 15:23:32
※ 引述《david830317 (dd810)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Xcode
: 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...)
: 問題(Question):
: 在xcode時用void以外不能用reture
: 錯誤結果(Wrong Output):
: Control may reach end of non-void function
: 程式碼(Code):(請善用置底文網頁, 記得排版)
: http://ideone.com/T36LJH
: 補充說明(Supplement):
關於這個 function 的寫法
float Quantity::calcValue() const
{
if (unit >= 1 && unit <= 10)
{
return unit * 3.00;
}
if (unit >= 11 && unit <= 50)
{
return unit * 2.50;
}
if (unit >= 51)
{
return unit * 2.00;
}
}
我比較建議用 if-elseif-elseif 的結構來寫:
float Quantity::calcValue() const
{
if (unit >= 1.0f && unit <= 10.0f) {
return unit * 3.00f;
} else if (unit > 1.0f && unit <= 50.0f) {
return unit * 2.50f;
} else if (unit >= 50.0f) {
return unit * 2.00f;
} else {
/* default */
return unit;
}
/* Unreached */
}
原因:
1. 這樣才看得清楚這三條 if 其實是負責同一件事,條件排列整齊後,漏網之魚也
在 default 那一區塊有處理,不管是 error handling 還是 return default,
而且所有的狀況在 if-else 結構內都會 return,能輕易判斷函式終結點。
2. float 運算時,不管是比大小還是運算,最好兩邊都是 float (10.0f),
你有些寫 int,問題倒還不大反正會轉成 float,但有些寫 double (2.50) 就
會兩邊都轉成 double 運算,運算完再轉 float 再 return,浪費效能。
另一個問題點,你大概一開始把 unit 定義為 int 後來才改 float,
所以 if 裡面完全沒有處理到 10.0f<unit<11.0f, 50.0f<unit<51.0f 的狀況,
如果習慣把常數的 data type 也寫對,遇到可能有問題的狀況,心中自然會產生
違和感,覺得這樣寫怪怪的。你寫 10.0f 時就會考慮 10.5f 會發生什麼事
3. 最後註解 Unreached 其實很有必要,照我的寫法所有狀況都應該在 if-else 的
結構內 return,所以不會跑到 Unreached 那邊。但就是有些人在修改 code 時
會呆呆加在後面,以為 if 跑完就會跑他加的東西,所以要註解提醒。
實務上有很多地方需要這樣的防呆措施,不只是合作寫程式防別人耍呆,很多
時候自己也會發蠢,
* * *
舉另一個經典例子:
if (unit > 1.0f)
return unit*3.0f;
這樣寫在 C/C++ 是允許的,省略大括號。但是就有人這樣插一行...
if (unit > 1.0f)
printf("Using 3.0 ratio.\n");
return unit*3.0f;
結果變成不管 unit 值多少,有沒有 print 那行字,都變成 return unit*3.0f 了
所以我會嚴格要求如果 if 的內容分成兩行寫,一定要加大括號
if (unit > 1.0f) {
return unit*3.0f;
}
或這樣也行
if (unit > 1.0f)
{
return unit*3.0f;
}
寫成同一行的話隨便你加不加
if (unit > 1.0f) return unit*3.0f;
大家應該會覺得是插入新行卻不長眼看清楚的那個人的錯,我也覺得是他的錯,
但是這種狀況實在太多太多了,大家都是用 Ctrl-C & Ctrl-V 在寫程式的樣子,
熬夜拼命貼的時候就常常貼錯地方,只好設法定一些規則防呆。
這樣至少你 code review 時就可以檢查大括號來預防出錯,而不是每次 release 的
前一天晚上才在抓幾百個這種無腦錯誤。
作者: MOONRAKER (㊣牛鶴鰻毛人)   2016-04-28 15:55:00
else if 不錯,清楚要求只有一個case執行也有人要求很長很大的if block不要用else而是要 if (flag) { ... } if (!flag) { ... } 的不過那是另外一回事情
作者: james732 (好人超)   2016-04-28 20:11:00
作者: CoNsTaR ((const *))   2016-04-29 12:42:00
用 monads 來寫最方便啦 XDD
作者: bibo9901 (function(){})()   2016-04-29 13:09:00
monad是個糟糕的設計
作者: CoNsTaR ((const *))   2016-04-29 13:13:00
是啊 它隱藏了不該隱藏的細節 可是就是方便嘛 XDD
作者: bibo9901 (function(){})()   2016-04-29 13:15:00
C又沒有綁手綁腳的"純"函數 跟本不必用monad啊
作者: chen20 (sOnE)   2016-04-29 21:59:00
推推

Links booklink

Contact Us: admin [ a t ] ucptt.com