匯東網


(轉載)C++ 巧用 include 合併不同類中相似的虛函數

[編輯] [转简体]
|
作者:huidong | 分類:【編程】C/C++
[ 25 瀏覽 0 評論 6 贊 5 踩 ]

概要

正文

以下內容轉載自知乎回答(有刪改) https://www.zhihu.com/question/564819820/answer/2750198351

北車註:原問題可以不看,看回答即可。若需要看也可以見 http://huidong.xyz/article.php?blog_id=474

知乎回答:

在 topling-zip 的 fsa(DFA, NFA 等等)庫中,爲了同時實現多態和性能,把內容相似的虛函數,放在單獨的頭文件中,然後在不同的實現類中 include 這些頭文件,就像這樣:

class Base {
public:
  virtual void foo() = 0;
};

class ConcretA : public Base {
  inline void low_level_operation() {...}
public:
  #include "foo_impl.h"
};

class ConcretB : public Base {
  inline void low_level_operation() {...}
public:
  #include "foo_impl.h"
};
// file foo_impl.h
void foo() override {
   while (some_condition()) {
      low_level_operation();
   }
}

其中 foo 是一個對外開放的 api,其實現需要用到一個 low_level_operation(),該 low_level_operation 的功能非常簡單,例如 fsa 中的 state_move,而 foo 則比較複雜,例如 prefix_match。

不同的 FSA,其 low_level_operation 的實現各不相同,但 foo 的實現完全相同,這在設計模式中,是典型的 template method,但需要把 low_level_operation 設計爲虛函數,這樣會引入很大的開銷,例如 DoubleArrayTrie 作爲 FSA 的實現時,其 state_move 超級簡單,爲此虛函數的開銷就不可忽視。

十多年前我最開始的實現就是 CRTP(前面已有其它答主詳細講解了,我就不再囉嗦),但是 CRTP 的問題有:

  1. 重度使用 template,例如簡單的 low_level_operation 調用,要寫成

    static_cast<const Derived*>(this)->low_level_operation()
  2. 編譯錯誤、Debug 信息晦澀難懂

  3. 多繼承時,麻煩更大

  4. 引入反向依賴

  5. 編譯速度慢

  6. 目標代碼尺寸大(主要是 Debug 信息會爆炸很多倍)

最終,我決定應用自己 20 年前總結的技巧:在 C 語言中實現模板函數的方法 - 知乎 (zhihu.com),再進一步精化,就得到了這個方案:返璞歸真。

[ 6] [ 5]


 評論區  0 條評論

+ 添加評論