2013-11-26 29 views
6

當返回類型需要更改時,哪些策略可用於棄用函數?例如,我有:如何在返回類型更改時棄用函數C++

BadObject foo(int); // Old function: BadObject is being removed. 
Object foo(int); // New function. 

ObjectBadObject是非常不同的內部,並交換它們的返回類型將打破代碼爲我的圖書館的現有用戶。我打算避免這種情況。

我可以標記BadObject foo(int) deprecated,並給用戶更改受影響的代碼的時間。
但是,我can't overload foo based on return-typefoo命名得非常好,它不需要額外的參數。如何在保留舊版本的同時將新功能添加到我的庫中,至少在一段時間內?

什麼是在不破壞過多依賴代碼的情況下棄用舊功能的策略,同時爲用戶提供遷移到新版本的時間?理想情況下,我會保留當前的函數名稱和參數列表,因爲它現在命名相當好。感覺這個應該是是一個相當普遍的問題:什麼是一個體面的方法來解決它?

+0

那麼,如果用戶在任何地方都使用auto,而不是手動鍵入返回類型,那麼所有內容都將自動運行:)。 – ScarletAmaranth

+0

現在這並沒有幫助你,但是C++ 11內聯命名空間是完美的。在'inline namespace v0'中聲明'foo',當需要修改時,在'inline namespace v1'中聲明'foo''(並從'v0'中移除'inline')。 – mythagel

回答

4

儘管解決方案強制您更改您的函數名稱,但它會是您的舊用戶和新用戶之間的妥協。

因此 - 將舊的foo更改爲deprecatedFoo,將新的foo更改爲foo2(或任何您想要的)。然後,在頭文件你包括你的圖書館,你可以簡單地說:

#define deprecatedFoo foo 

,並在函數內部本身做:

#warning ("This function is deprecated. Use 'foo2' or change the #define in LINE in file HEADER.") 

老版本的用戶將不必改變自己的代碼,並會發出警告,新用戶可能會收聽並更改#define以便使用新的foo

在下一個版本中,您只需刪除舊的foodefine

+1

你是否認爲'#define'是另一種方式?因爲新功能的用戶將獲得與舊功能用戶相同數量的警告。 – aschepler

+0

新版本的用戶應該會收到警告,因此他們可以(如果他們想要)更改。如果您以相反的方式執行'#define',代碼將不會與舊版本兼容。但我想這是OP必須做的選擇,我們不是討論這個問題的選擇。 –

0

我認爲一個典型的例子是Boost's Spirit

從他們FAQ

雖然引入精神V2我們重組在 順序目錄結構,以適應在同一時間兩個版本。所有 Spirit.Classic現在住在目錄

升壓/精神/家庭/經典

,其中上面的目錄包含轉發標題到新 位置允許保持應用程序的兼容性。 轉發標頭髮出警告(從Boost V1.38開始),告知 用戶更改其包含路徑。請期待上面的 目錄/轉發頭很快就會消失。

這解釋了目錄

升壓/精神的需要/包括

其中包含轉發標題爲好。但這次標頭 不會消失。我們鼓勵應用程序編寫人員僅使用包含在此目錄中的 包括。這允許我們在需要時重建 下面的目錄,而不必擔心應用程序 的兼容性。請僅在您的應用程序中使用這些文件。如果它 事實證明某些轉發文件丟失,請將其報告爲 的一個錯誤。

您可以通過將新版本和舊版本保留在單獨的目錄中並使用轉發標頭來保持兼容性來緩解遷移。用戶最終將被迫使用新的標題。

SDL 2.0有不同的方法。它們不提供兼容性層,而是提供遷移指南,讓用戶通過最顯着的變化。在這種情況下,您可以幫助用戶瞭解他們需要重構其代碼的方式。

0

如果要讓Object類繼承BadObject(您將暫時保留)該怎麼辦?然後舊的用戶代碼不會知道這一點,所以它不會中斷,只要你的新「foo」函數仍能正確返回你的對象。