0

私の質問は、C++ クラスでインターフェイスと実装を分離するツールとしてのパブリック継承とプライベート継承の組み合わせに関するものです。このパターンでは、インターフェース基本クラスは共通関数 ( class Base0) を宣言します。共通の実装は、インターフェイス ベース ( ) から仮想的に派生したクラスで実行されますclass Impl0 : virtual public Base0。このクラスには、すべての共通データ メンバーが含まれます。拡張クラスは 2 つのステップで作成されます。最初に、拡張インターフェースは、インターフェース・ベース ( class Base1 : virtual public Base0) からの仮想継承によって定義されます。次に、拡張実装は、(インターフェイスの場合) からパブリックに派生し、 (実装の場合)Base1からプライベートに派生することによって実行されます。私の質問は次のとおりです。Impl0class 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。この複製を回避する方法はありますか?

4

2 に答える 2

1

MathOps_Extn_Impl の m_y の複製に注意してください。この複製を回避する方法はありますか?

はい。MathOps_Impl::m_y protectedの代わりにアクセス権を与えますprivate

派生クラスがプライベート データにアクセスできない理由を明示的に尋ねています。それは設計によるものです。

于 2013-01-17T22:41:22.833 に答える
0

共通実装クラスの保護されたメンバー関数を使用して、カプセル化を解除することなく、共通データへのアクセスを許可できます。

無料の例は次のとおりです:)

#include <cstdio>

class Math
{
public:
    virtual ~Math() {}
    virtual int add(int b) const = 0;
};

class MoreMath : public virtual Math
{
public:
    virtual ~MoreMath() {}
    virtual int subtract(int b) const = 0;
};

class MathImpl : public virtual Math
{
private:
    int m_a;

public:
    MathImpl(int a) : m_a(a) {}
    virtual ~MathImpl() {}
    int add(int b) const { return m_a + b; }

protected:
    int value() const { return m_a; }
};

class MoreMathImpl : public virtual MoreMath, private MathImpl
{
public:
    MoreMathImpl(int a) : MathImpl(a) {}
    int subtract(int b) const { return value() - b; }
};

int main()
{
    MoreMath* one = new MoreMathImpl(1);
    printf("1 + 2 = %d\n", one->add(2));
    printf("1 - 2 = %d\n", one->subtract(2));
    delete one;

    return 0;
}
于 2013-01-18T02:08:11.193 に答える