0

基本クラスのインスタンスからすべての変数を変更できる派生クラスを作成するにはどうすればよいですか? 基本クラス変数を静的に宣言できることは理解していますが、そうすると、関数を使用してそれらを初期化することができず、コードが非常にメッセージになり、編集が難しくなります。

これはクラスの例です。c2 が theC1 クラスの x を編集しないのはなぜですか。theC1 ではない c1 クラスを参照している場合、参照しているのは何ですか?

#include <stdio.h>

class c1
{
public:
    c1( int d )
    {
        x = d;
    }
    int x;
};

class c2 : public c1
{
public:
    c2( c1& ref )
        :
    c1( ref )
    {};
    void setx()
    {
        x = 5;
    }
};

int main () 
{
    c1 theC1(4);
    c2 theC2(theC1);
    theC2.setx();

    printf( "%d\n",theC1.x );
    printf( "%d\n",theC2.x );

    return 0;
}
4

2 に答える 2

2

c1オブジェクトへの参照を保存するのではなく、参照を使用して のコピー コンストラクターを呼び出していc1ます。次のようなものが必要です。

class c2 : public c1
{
public:
    c2( c1& ref )
        : c1_ptr(&ref) {}

    void setx()
    {
        c1_ptr->x = 5;
        this->x   = 5;
    }
private:
    c1 * c1_ptr;
};

ただし、これには のデフォルト コンストラクタが必要ですc1。まったく構築したくない場合は、プロキシ クラスを使用することをお勧めします。

class c1_proxy
{
public:
    c1_proxy( c1& ref )
        : x(ref.x), c1_ptr(&ref) {}

    void setx()
    {
        c1_ptr->x = 5;        
    }
    int & x;
private:
    c1 * c1_ptr;
};

しかし、私はこれをアンチパターンと考えています。すべての値を手動で更新する必要があることに注意してください。

于 2013-04-04T08:44:37.283 に答える
1

theC1theC2は完全に別のインスタンスです。参照によって初期化されるtheC2type のサブオブジェクトを含みますが、それは依然として (そして常にそうなるでしょう) とは異なるインスタンスです。基本クラスのサブオブジェクトはすべてのインスタンスのメンバーであり、これをorの他のインスタンスと「共有」する方法はありません。c1refc1theC1c2c2c1

それがあなたが求めているセマンティクスである場合、c2そこから派生する代わりに参照を内部に保存してアクセスすることができます。c1コードは次のようになります。

class c1
{
public:
    c1( int d )
    {
        x = d;
    }
    int x;
};

class c2
{
    c1 &myC1;
public:
    c2( c1& ref )
        :
    myC1(ref)
    , x(myC1.x)
    {}
    void setx()
    {
        myC1.x = 5;
    }
    int &x;
};

もちろん、 をx公開して上記のコードのような参照トリックに頼らなければならないよりも、 をカプセル化する方がよいでしょう。

アップデート

これを大規模に実装する 1 つの方法は、同じインターフェイスc1を実装し、インスタンスが の「データ インスタンス」を共有することです。c2c2c1

#include <memory>


struct c1_iface
{
  virtual int getX() const = 0;
  virtual void setX(int newX) = 0;
};


class c1 : public c1_iface
{
  int x;

public:
  virtual int getX() const { return x; }
  virtual void setX(int newX) { x = newX; }
};


class c2 : public c1_iface
{
  std::shared_ptr<c1> data_;

public:
  explicit c2(std::shared_ptr<c1> data) : data_(data) {}

  virtual int getX() const { return data_->getX(); }
  virtual void setX(int newX) { data_->setX(newX); }
};

C++11 にアクセスできない場合は、boost::shared_ptr代わりに使用できます (または、手動共有を使用するだけで、あまりお勧めしません)。

少し汚れた代替手段として、共有ポインター (またはそれに相当するもの) を移動しc1_ifaceて、関数を非抽象化し、逆参照することができます。

于 2013-04-04T08:49:47.693 に答える