Reputation: 405
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
Reputation: 171197
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
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