組み込みのソフト開発でコールバック関数の実装をしようとしております。
C++でコールバックを実装する場合、主に以下の2パターンの認識です。
(もしほかの方法(関数ポインタ以外)があればご教示いただきたいです。)
それぞれ、メリットとデメリットを教えていただけないでしょうか。
個人的には、純粋仮想関数を使う方法がベターだと考えているのですが、
C++の経験が浅く、知らないことも多いため、気になったため質問させていただきます。
メモリやCPUリソースに余裕が無いため、なるべくコストが少ない方法を選びたいです。
◆1. 仮想関数(純粋仮想関数)で定義された関数を呼ぶ。
C++
1#include <stdio.h> 2 3//下位層 4class Callback{ 5 public: 6 //投げるコールバック一覧を宣言 7 virtual void cb_func(void) = 0; 8}; 9class Task{ 10 public: 11 //上位層のコールバック先クラスのインスタンスを保存 12 Task(Callback* func) : func_(func){}; 13 void Start(void){ 14 //コールバック 15 func_->cb_func(); 16 } 17 private: 18 Callback* func_; 19}; 20 21//上位層 22class CbImpl : public Callback { 23 //コールバックを受けるクラスの定義 24 virtual void cb_func() override { 25 printf("call func."); 26 } 27}; 28int main(void){ 29 Callback* cb = new CbImpl(); 30 Task* tsk = new Task(cb); 31 //実行 32 tsk->Start(); 33 return 0; 34}
◆2. 関数ポインタをstd::functionで受け取ってそれを呼び出す。
C++
1#include <stdio.h> 2#include <functional> 3 4//下位層 5class Task{ 6 public: 7 //上位層の関数ポインタを保存 8 Task(std::function<void(void)> func): func_(func){}; 9 void Start(void){ 10 //コールバック 11 func_(); 12 } 13 private: 14 std::function<void(void)> func_; 15}; 16 17//上位層 18//コールバックを受ける関数の定義 19void abc(void){ 20 printf("call func."); 21} 22int main(void){ 23 Task* tsk = new Task(abc); 24 //実行 25 tsk->Start(); 26 return 0; 27}
下記はそれぞれ、私の知っている(聞いたことのある)範囲のメリット・デメリットです。
1のパターンだと、
・VTableができて、メモリ使用量が少し増加する。(デメリット)
・VTableの分、呼び出しに少しオーバーヘッドがある。(デメリット)
・コールバック関数の実装漏れが無い(メリット)
2のパターンだと、
・std::functionを使うとコンパイラの最適化がされない。(デメリット)
・std::functionを使うとメモリ使用量が増加する。(デメリット)
・呼び出し時にオーバーヘッドがある。(デメリット)
よろしくおねがいします。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/16 15:09
2020/09/17 01:41 編集