Joel
Joel

Reputation: 405

Derived class from class instance?

how do I make a derived class which can change all the variables from an instance of its base class? I understand I could declare the base class variables static, but when I do that I cannot initialise them using functions, which makes the code very message and difficult to edit.

This an example class; why does c2 not edit x in the theC1 class. If it is referencing to a c1 class which is not theC1, then what is is referencing to?

#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;
}

Upvotes: 0

Views: 325

Answers (2)

theC1 and theC2 are completely separate instances. theC2 contains a subobject of type c1 which is initialised by the reference ref, but it's still (and always will be) a different instance of c1 than theC1. The base class subobject is a member of every c2 instance and there's no way to make this "shared" with any other instance of c2 or c1.

You could store the reference inside c2 and access that instead of deriving from c1 if that is the semantics you're after. The code would then look like this:

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;
};

Of course, it would be better to encapsulate x, rather than have it public and have to resort to reference tricks like those in the code above.

UPDATE

One way to implement this on a larger scale could be c1 and c2 implementing the same interface, and c2 instances sharing a "data instance" of c1:

#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); }
};

If you don't have access to C++11, you can use boost::shared_ptr instead (or just use manual sharing, not really recommended).

As a slightly dirtier alternative, you could move the shared pointer (or its equivalent) into c1_iface and make the functions non-abstract, dereferencing it.

Upvotes: 1

Zeta
Zeta

Reputation: 105995

You're using a reference to call the copy constructor of c1, not saving a reference to a c1 object. You want something like this:

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

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

However, this needs a default-constructor for c1. If you don't want any construction at all, you might want to use a proxy class:

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;
};

However, I consider this as an antipattern. Note that you have to update all values by hand.

Upvotes: 2

Related Questions