2013-07-04 30 views
0

假設我使用它實現的功能foo圖書館和我的代碼可能是這個樣子:對API的功能參數常量,正確性改變

void foo(const int &) { } 

int main() { 
    int x = 1; 
    foo(x); 
    std::cout << (1/x) << std::endl; 
} 

,一切工作正常。但是現在假設foo由於某種原因被修改或重載。現在我們得到的可能是這樣的:

void foo(int & x) { 
    x--; 
} 
void foo(const int &) {} 

int main() { 
    int x = 1; 
    foo(x); 
    std::cout << (1/x) << std::endl; 
} 

BAM。程序突然中斷。這是因爲我們真的想要在片段中傳遞的是一個常量引用,但是隨着API突然更改,編譯器會選擇我們不想要的版本,並且程序意外中斷。

我們想要的東西實際上是這樣的:

int main() { 
    int x = 1; 
    foo(static_cast<const int &>(x)); 
    std::cout << (1/x) << std::endl; 
} 

用此修復程序,該程序再次開始工作。不過,我必須說,我沒有看到許多這樣的代碼,因爲大家似乎都相信這種類型的錯誤不會發生。另外,這似乎是不必要的冗長,如果有多個參數並且名稱開始變長,函數調用就會變得非常混亂。

這是一個合理的關注點,我應該怎麼做呢?

+2

這不是'const_cast'的目的,它的目的是_remove_類型的'const'限定。你的例子''static_cast'也可以。 –

+0

@CaptainObvlious http://www.cplusplus.com/doc/tutorial/typecasting/在這裏它說:「這種類型的鑄造操縱對象的常量,要麼被設置要麼被刪除。」這是不正確的? – Svalorzen

+0

@Svalorzen它可以用於此,但它不應該。這不是該任務的最小工具。該任務的最小工具是'static_cast'。 – 2013-07-04 23:01:11

回答

1

如果你改變一個帶有const引用的函數,使它不再是一個const,那麼你可能會破壞一些東西。這意味着你必須檢查每個調用該函數的地方,並確保它是安全的。進一步有兩個相同名稱的函數,在這種情況下有一個const和一個沒有const的函數肯定是一個糟糕的計劃。

正確的做法是創建一個新函數,該函數執行x--變體,其名稱與現有名稱不同。

,做這樣的事情應該是嚴厲和體罰,可能與是否有文件說:「我們已經改變了功能foo在一個大的通知參與略少暴力的API供應商,現在遞減x除非參數是強制轉換爲const「。這是人們可以想象的最糟糕的二進制缺陷之一(用「很難發現哪裏出了問題」)。

+0

看起來很奇怪,但作爲一個API用戶,沒有方便的方法來防止意外錯誤。將參數強制轉換爲const似乎是一種相對痛苦而又有用的方法,可以避免任何可變修改的發生。 – Svalorzen

+0

如果「main」對它沒有改變很重要,你可以首先聲明'x' const。但實際上,如果有人在他們的API中執行此操作,他們的API將無法升級到新版本。你可以用比這少得多的數量讓你的用戶感到不安。它已經取得4個次要版本的Python,以便Python 3.4現在向後兼容2.7的語法。不,他們不希望倒退,但沒有人(差不多)使用3.0到3.3,因爲你必須修改很多代碼(特別是庫)。 –

+0

api編寫器可以像添加過載一樣輕鬆地更改函數。或'const_cast'離開'const'。一個新的api是一個新的API:如果作者不可靠,這是不可靠的。 – Yakk