跳轉到內容

更多 C++ 慣用法/函式中毒

來自 Wikibooks,開放書籍,開放世界

函式中毒

[編輯 | 編輯原始碼]

隱藏或禁止使用某些函式,支援更好的替代方案。

通常,在與具有 C 或 C++11 前介面的庫互動時,由於現代 C++ 表達能力更強,因此隱藏(對正在專案中工作的人員來說)所有(或僅僅是許多)分配記憶體並返回原始指標(如 T*)的函式,並用更友好的 RAII 方法(如 unique_ptr)替換它們非常方便。

解決方案和示例程式碼

[編輯 | 編輯原始碼]
// header of external library

foo* create_foo();
foo_destroy(foo*);

// our header, with our enhanced version

struct foo_deleter {
    void operator()(foo* h) {
        // foo_destroy provided by the 3rd party library as function, macro, ...
        foo_destroy(h);
    }
};
using unique_foo = std::unique_ptr<foo, foo_deleter>;


inline unique_foo create_unique_foo() {
    // we do not have poisoned create_foo yet!
    return unique_foo{create_foo()};
}
#pragma GCC poison create_foo
// from now on, no-one can use create_foo again!
// at least with GCC and clang

禁止函式的指南

如果函式 g 是庫 L 中函式 f 的嚴格替換,那麼

  • g 提供了比 f 更明顯的優勢(例如將解構函式中的析構器替換為手動呼叫)
  • g 可以作為 f 的直接替換,這意味著
    • 它可以在不編寫多於一行沒有明顯缺點的粘合程式碼的情況下與庫 L 互動
    • 在程式碼庫中將 f 更新為 g 是一個簡單的操作(使用更改所有出現或簡單的查詢和替換)
    • 刪除 f 的成本不太高
  • gf 相比沒有任何缺點,這意味著
    • 它與 f 相比沒有新增任何可衡量的執行時開銷
    • 它沒有新增任何新的依賴項
    • 它不能降低型別安全性、異常安全性或執行緒安全性
    • 它不能引入新的程式設計錯誤型別
  • gf 相比不會降低可讀性或隱藏意圖,這意味著
    • 不需要記錄 g 的作用,因為它應該與 f 一樣,只有在那些對每個人都不清楚的情況下才需要記錄其優點。

因此,如果 gf 的嚴格替換,那麼可以在程式碼庫中禁止 f

已知用途

[編輯 | 編輯原始碼]

用具有改進功能的函式替換不能刪除的函式(例如,如果它是外部庫的一部分)。

[編輯 | 編輯原始碼]

參考文獻

[編輯 | 編輯原始碼]
華夏公益教科書