yohhoyの日記

技術的メモをしていきたい日記

異種クラス同名メンバ関数の個別オーバーライド

プログラミング言語C++において、異なる基底クラスに属する同名メンバ関数*1を個別にオーバーライドする方法。

// 同名メンバ関数をカスタマイズポイントとして提供する
// 互いに無関係なインタフェースクラス
struct Interface1 {
  virtual void process() = 0;
};
struct Interface2 {
  virtual void process() = 0;
};

// インタフェース実装クラス
struct Derived: Interface1, Interface2 {
  void process() override { /*...*/ }
  // Interface1::process と Interface2::process を
  // 同時にオーバーライドするため実装分離は不可能
};

インタフェース別にprocessメンバ関数オーバーライドする中間クラスを定義し、別名メンバ関数(process1, process2)への処理委譲によって個別オーバーライドを可能とする。

// メンバ関数名を変換するプロキシインタフェース
struct ProxyInterface1 : Interface1 {
  void process() override final { return process1(); }
  virtual void process1() = 0;
};
struct ProxyInterface2 : Interface2 {
  void process() override final { return process2(); }
  virtual void process2() = 0;
};

// インタフェース実装クラス
struct Derived: ProxyInterface1, ProxyInterface2 {
  void process1() override { /*A*/ }
  void process2() override { /*B*/ }
  // 下記はコンパイルエラーとして検出
  // void process() override {}
};

Derived obj;
Interface1& if1 = obj;  if1.process();  // A
Interface2& if2 = obj;  if2.process();  // B

関連URL

*1:厳密には同一シグネチャ(→id:yohhoy:20210927)をもつ仮想関数。