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

theC1并且theC2是完全独立的实例。theC2包含一个c1由 reference 初始化的类型的子对象ref,但它仍然(并且总是)是c1than的不同实例theC1。基类子对象是每个实例的成员,无法与orc2的任何其他实例“共享” 。c2c1

您可以将引用存储在内部并访问它,而不是从您所追求的语义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,而不是将其公开并不得不求助于上面代码中的引用技巧。

更新

在更大规模上实现这一点的一种方法可能是实现相同的接口,并且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 回答