私の質問は、C++ クラスでインターフェイスと実装を分離するツールとしてのパブリック継承とプライベート継承の組み合わせに関するものです。このパターンでは、インターフェース基本クラスは共通関数 ( class Base0
) を宣言します。共通の実装は、インターフェイス ベース ( ) から仮想的に派生したクラスで実行されますclass Impl0 : virtual public Base0
。このクラスには、すべての共通データ メンバーが含まれます。拡張クラスは 2 つのステップで作成されます。最初に、拡張インターフェースは、インターフェース・ベース ( class Base1 : virtual public Base0
) からの仮想継承によって定義されます。次に、拡張実装は、(インターフェイスの場合) からパブリックに派生し、 (実装の場合)Base1
からプライベートに派生することによって実行されます。私の質問は次のとおりです。Impl0
class Impl1 : public virtual Base1, private Impl0
(1) 拡張クラスの関数が で共通データを必要とする関数を定義している場合、Impl0
そのデータを Impl1 で複製する必要がありますか?
(2) この複製を回避する方法はありますか?
最小限の例として、add()、substr()、mult()、および div() の 4 つの基本的な算術関数を実装するためのクラス階層を考えてみます。基本バージョンのMathOps
には、add() および subtr() 関数が含まれています。拡張バージョン にはMathOps_Extn
、mult() と div() が含まれています。上記の手法により、次のクラス階層が得られます。
#include<iostream>
using std::cout;
using std::endl;
class MathOps {
public:
virtual int add(int x) = 0;
virtual int subtr(int x) = 0;
};
class MathOps_Impl : public virtual MathOps {
private:
int m_y;
public:
MathOps_Impl(int y) : m_y(y) {
cout << "MathOps_Impl initialized with value: " << m_y << endl;
}
virtual int add(int x) { return x + m_y;}
virtual int subtr (int x) { return m_y - x;}
};
class MathOps_Extn : public virtual MathOps {
// Extends MathOps by adding mult() and div()
public:
virtual int mult(int x) = 0;
virtual int div(int x) = 0;
};
class MathOps_Extn_Impl : public virtual MathOps_Extn, private MathOps_Impl {
private:
int m_y; // Have to replicate member data m_y here.
public:
MathOps_Extn_Impl(int y) : MathOps_Impl(y), m_y(y) {
cout << "MathOps_Extn_Impl initialized with value: " << m_y << endl;
}
virtual int mult(int x) {
return x * m_y;
}
virtual int div(int x) {
int quotient = x == 0? 0 : m_y/x;
return quotient;
}
};
int main() {
MathOps_Extn* B = new MathOps_Extn_Impl(10);
cout << "add 20: " << B->add(20) << endl;
cout << "subtr 20: " << B->subtr(20) << endl;
cout << "mult 2: " << B->mult(2) << endl;
cout << "div 5: " << B->div(5) << endl;
の複製に注意してm_y
くださいMathOps_Extn_Impl
。この複製を回避する方法はありますか?