4

抽象クラスの入力パラメーターを変更せずに、特定の階層内の派生クラスに対して機能する関数を作成したいと考えています。

class A {
public:
    A(int val): m_i(val) { }
    virtual void add(int i) = 0;

    int m_i;
};

class B: public A {
public:
    B(int val): A(val) { }
    B(): A(0) { }
    virtual void add(int i) { m_i += i; }
};

class C: public A {
public:
    C(int val): A(val) { }
    C(): A(0) { }
    virtual void add(int i) { m_i += i*2; }
};

int f(const A& base_class)
{
    // how to create a concrete copy of class base_class?
    base_class.add(5);
}

ここで、f() は B と C の両方で機能するはずですが、dynamic_cast を使用しない限り、実際の型がわからないため、具象クラスのコピーを作成できません。

この問題を解決する別の方法はありますか、それとも dynamic_cast を使用する必要がありますか?

4

3 に答える 3

3

仮想コンストラクタ イディオムとして一般に知られている典型的なアプローチは、具体的なクラスを複製するための別の仮想メソッドを定義し、それを抽象ベースで仮想化し、必要に応じてそれを呼び出して、その型を知らなくても目的のクラスのインスタンスを生成することです。

class A {
public:
    A(int val): m_i(val) { }
    virtual void add(int i) = 0;
    virtual A* clone() const = 0; // Override in derived classes to return new B/C
    int m_i;
};
于 2013-03-28T14:33:49.473 に答える
1

なぜコピーを作成する必要があるのか​​ 、あなたの質問からは明らかではありません。

ただし、そうする場合は、次のclone()方法があります。

class A {
public:
    virtual A* clone() const = 0;
};

class B: public A {
public:
    virtual B* clone() const { return new(*this); }
};

class C: public A {
public:
    virtual C* clone() const { return new(*this); }
};
于 2013-03-28T14:33:58.113 に答える
1

問題は、あなたが渡しているconst A&が、修飾子を取り除くとメソッドaddではないということです。これは機能します:constconst

int f(A& base_class)
{
    // how to create a concrete copy of class base_class?
   base_class.add(5);

   ///Need a return here
}

私が使用gccしていて、実際に何が起こっているかを示すエラーは次のとおりです。

error: no matching function for call to 'A::add(int&) const'
  base_class.add(a);                                  ^^^^^  

no known conversion for implicit 'this' parameter from 'const A*' to 'A*'
                                                        ^^^^^^^^

あなたの応答に基づいて、他のオプションは makem_i mutableであり、メンバーメソッドを次のconstように作成します。

class A {
  public:
    A(int val): m_i(val) { }
    virtual void add(int i) const = 0;

  protected:
    mutable int m_i;
};

class B: public A {
 public:
    B(int val): A(val) { }
    B(): A(0) { }
    virtual void add(int i) const { m_i += i; }
};

class C: public A {
  public:
    C(int val): A(val) { }
    C(): A(0) { }
    virtual void add(int i) const { m_i += i*2; }
};

int f(const  A& base_class)
{
    base_class.add(5) ;

    //Need a return here
}
于 2013-03-28T14:38:07.743 に答える