2


1

純粋な仮想基本クラスで明示的な関数を作成せずに、コピーの作成を行うことができますか?

私の目的はクラスの詳細コピーを行うことですが、仮想クラスが問題を引き起こしています。

#include
using namespace std;

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
};

class Handler:public Vir
{
    public:
    int i;
    Handler() {}
    Handler(int val):i(val) {}
    void hi() {cout<<"Value of i="<setI(c.getI());
    }
    int getI()const {return v->getI();}

    void initialize() {v=new Handler(10);}
    void hi() {v->hi();}
    ControlPanel() {}
    ~ControlPanel() {delete v;}
};

int main()
{
    ControlPanel cc;
    cc.initialize();
    cc.hi();
    ControlPanel bb(cc);//copying cc into bb
}

コンパイルエラーメッセージ:

test.cpp: In copy constructor ‘ControlPanel::ControlPanel(const ControlPanel&)’:
test.cpp:28: error: ‘class Vir’ has no member named ‘setI’
test.cpp: In member function ‘int ControlPanel::getI() const’:
test.cpp:30: error: ‘class Vir’ has no member named ‘getI’

Virから継承し、独自の一意のメンバー(float a;またはdouble b;など)を持つハンドラークラス(Handler1、Handler2など)をさらにたくさん用意する予定です。 したがって、すべてのHandlerクラスのすべてのgetterおよびsetter関数をVirクラスに保持するのは意味がありません。 メンバーはHandlerクラスに固有であるため、Handlerクラスにはgetterおよびsetterメソッドを保持します。 コンパイラはそうすることを許可していません。 助けて?

6 Answer


2


抽象クラスに `duplicate()`関数を追加します。これは(各派生クラスで)適切な値で新しいインスタンスを作成し、それを返します。 あるいは、正しいタイプからコピーしていることを確認するためにチェックする `copyFrom(Abs other)`関数を検討してください。そうであれば、フィールドをコピーします。

一般に、ControlPanelクラスにAbsオブジェクトへの参照がある場合、具体的なHandlerオブジェクトを検査して複製を試みてはならず、そのオブジェクトの仮想関数に複製を渡す必要があります。


2


たぶん私は何かを見逃していますが、あなたは Vir`の仮想 clone`メソッドでもっと良くないでしょうか? これは、あなた自身の答えで概説されている `ControlPanel`コピーコンストラクターでの厄介なキャストを回避できることを意味します。 これは、@ Andrew Aylettがhttps://stackoverflow.com/questions/3813964/cant-copy-construction-be-done-without-creating-an-explicit-function-in-the-pure/3829394#で提案しているものと同じです。 3829394 [彼の答え]「クローン」の代わりに「複製」が使用されています。

何かのようなもの

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

これは `Handler`に実装され、

Handler* Handler::clone() const
{
    return new Handler( *this );
}
共変の戻り値型の使用に注意してください。 `Handler

clone`は、単に` Vir * ではなく Handler * を返すことができますが、それでも Vir :: clone`の有効なオーバーライドです。

これにより、 `ControlPanel`コピーコンストラクターが単純になります。

ControlPanel( const ControlPanel& c )
    : v( c.v->clone() )
{
}


0


コンパイラーがなぜ許可するのですか? これらのメソッドは、そのインターフェイスにはありません。

Factory Patternを使用して、 Vir`を作成し、すべてのコンストラクターを Vir`のインターフェースに追加する必要を回避できます。 また、http://en.wikipedia.org/wiki/RAII [RAII]を使用して、initialize()スタイル関数を回避することを検討する必要があります。


0


「Vir * v」を「Handler * v;」に変更し、コードがコンパイルされるかどうかを確認します。

クラス Vir`は、 setI() および getI() `メンバー関数を宣言/定義しません。

または、「Vir」を

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI()const =0;
    virtual void setI(int)=0;
};


0


サブクラス経由でアクセスできるようにするには、「Vir」で「getI」と「setI」を(純粋な)仮想として定義する必要があります。 これを回避する方法はありません。


0


スティーブが提案したように、私は友人が私に解決策を与えたので、私自身の質問に答えています。 これが、仮想クラスが障害となる可能性のあるC ++でディープコピーを実行する方法について疑問のある方に役立つことを願っています。 誰かがこれが役に立つことを願っています。

#include
using namespace std;

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI() {std::cout << "Inside Base class" << std::endl;}
    virtual void setI(int i) {cout<<"In base"<setI(10);abc=222;}
    void hi() {v->hi();}
    ControlPanel() {}
    ~ControlPanel() {delete v;}
};

int main()
{
    ControlPanel cc;
    cc.initialize();
    cc.hi();
    cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
    cout<<"x value cc="<<(cc.v)->getX()<i::" << (bb.v)->getI() << endl;
    cout<<"x value bb="<<(bb.v)->getX()<setI(999);
    (cc.v)->setX(888888888);
    cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
    cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
    cout<<"x value cc="<<(cc.v)->getX()<