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

StackOverflow https://stackoverflow.com/questions/3813964

質問

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

#include<iostream>
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="<<i<<endl;}
    int getI() const {return i;}
    void setI(int j) {i=j;}
};

class ControlPanel
{
    public:
    Vir *v;
    ControlPanel(const ControlPanel& c)//copy constructor
    {
        v=new Handler;
        v->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; など) を持つハンドラー クラス (Handler1、Handler2 など) をさらにたくさん用意する予定です。またはダブルb;等)。したがって、すべての Handler クラスのすべてのゲッター関数とセッター関数を Vir クラスに保持することは意味がありません。メンバーは Handler クラスに固有であるため、getter メソッドと setter メソッドを Handler クラス内に保持したいと考えています。コンパイラがそれを許可していません。ヘルプ?

役に立ちましたか?

解決

もしかしたら何かが足りないかもしれませんが、仮想の方が良いのではないでしょうか? clone メソッドオン Vir?つまり、 ControlPanel あなた自身の答えで概説されているコピーコンストラクター。これは、@Andrew Aylett が示唆していることと同じです。 彼の答えduplicate の代わりに使用されています clone.

何かのようなもの

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

で実装されています Handler することが

Handler* Handler::clone() const
{
    return new Handler( *this );
}

共変の戻り値の型の使用に注意してください。 Handler::clone を返すことが許可されています Handler* ただではなく Vir* そして依然として有効なオーバーライドである Vir::clone.

これにより、 ControlPanel コンストラクターを単純にコピーする

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

他のヒント

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

あなたのControlPanelクラスは、ABSオブジェクトへの参照を持っている場合は、一般的に、具体的なHandlerオブジェクトを検査することによって、その重複をやろうとすべきではない、それはそのオブジェクト上の仮想関数を切る重複を渡す必要があります。

なぜコンパイラはあなたをできるようになりますか?これらの方法は、そのインターフェイスではありません。

あなたはすべてを追加することを避けるために、あなたのVirを作成するために、ファクトリパターンを使用することができますVirのインターフェイスにコンストラクタ。あなたはまた、初期化()スタイルの関数を避けるために RAII の使用を検討する必要があります。

Vir *v

変更Handler *v;とあなたのコードのコンパイルかどうかを参照してください。

あなたのクラスVirsetI()getI()メンバー関数を定義/宣言していません。

または

としてVirを定義します
class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI()const =0;
    virtual void setI(int)=0;
};

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

スティーブが示唆したように友人が私に解決策を与えただって

、私は自分の質問に答えますよ。希望は、この仮想クラスはバリケードかもしれC ++でディープコピーを行う方法の疑問を持っている誰にも助けになるでしょう。ホープ誰かが、これは重宝ます。

#include<iostream>
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"<<endl;}
    virtual int getX() {}
    virtual void setX(int x) {}
};
class Model
{
    public:
    int x;
    Model(const Model& mm) {x=mm.x;}
    Model():x(555) {cout<<"Model constructor called"<<endl;}
    int getX() {return x;}
    void setX(int xx) {x=xx;}
};

class Handler:public Vir
{
    public:
    int i;
    Model *m;

    Handler() {m=new Model;cout<<"Handler constructor called"<<endl;}
    Handler(const Handler& h)
    {
    std::cout << "Inside Handler @lineNumber:" << __LINE__ << std::endl;
    i=h.i;
    m=new Model(*h.m);
    }
    Handler(int val):i(val) {}
    ~Handler() {delete m;}
    void hi() {cout<<"Value of i="<<i<<endl;}
    int getI() {return i;}
    void setI(int j) {i=j;}
    int getX() {return m->getX();}
    void setX(int xx) {m->setX(xx);}
};

class ControlPanel
{
    public:
    int abc;
    Vir *v;
    ControlPanel(const ControlPanel& c)//copy constructor
    {
    std::cout << "Inside ControlPanel @lineNumber:" << __LINE__ << std::endl;
        v=new Handler((Handler&)*(c.v));
    }
    void initialize() {v=new Handler();v->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()<<endl;
    ControlPanel bb(cc);//copying cc into bb
    cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
    cout<<"x value bb="<<(bb.v)->getX()<<endl;
    (cc.v)->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()<<endl;
    cout<<"x value bb="<<(bb.v)->getX()<<endl;
}//main
/*
Output:
Model constructor called
Handler constructor called
Value of i=10
(cc.v)->i::10
x value cc=555
Inside ControlPanel @lineNumber:52
Inside Handler @lineNumber:32
(bb.v)->i::10
x value bb=555
(cc.v)->i::999
(bb.v)->i::10
x value cc=888888888
x value bb=555  */
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top