Reputation: 103
I quite often confront myself to this problem. Let's say I have these classes:
class B
{
public:
virtual std::string className(){return "B";}
};
class A
{
public:
A()
: _B(new B)
{}
virtual std::string className(){return "A";}
virtual void desc()
{
std::cout << "I am " << className() <<
" and I own: " << _B->className() << std::endl;
}
protected:
B * _B;
};
Then, I want to extend A
and B
with new information. I am sure that SuperA
and SuperB
have a "is-a" relationship with A
and B
, respectively. The straightforward way would be to do try inheritance:
class SuperB: public B
{
public:
virtual std::string className(){return "SuperB";}
}
class SuperA: public A
{
public:
SuperA()
: A()
, _superB(new SuperB)
{}
virtual std::string className(){return "SuperA";}
virtual void desc()
{
std::cout << "I am " << className() <<
" and I own: " << _superB->className() << std::endl;
}
protected:
SuperB * _superB;
};
But this is obviously not good, since SuperA
would have actually two B
s: the one from the A
class, and the other from its SuperB
class. And the override of desc
is not so elegant.
I can see that I could have setters and getters on B*
in A
and override them in SuperA
to use a SuperB
instead of a B
, and never refer to to B*
directly and always use the getter, but this seems a bit intrusive for A
.
Trying to compose, i.e. having SuperA
owning an A*
instance does not look better either.
And it gets even harder if A
owns not a single B*
but a say std::vector<B*>
.
Is this a common problem? Is there an elegant solution that I don't see for it?
Upvotes: 2
Views: 122
Reputation: 303097
You could just have A
have a protected constructor that takes a B*
:
class A {
public:
A()
: _B(new B)
{ }
protected:
A(B* b)
: _B(b)
{ }
};
So that:
class SuperA : public A {
public:
SuperA()
: A(new SuperB)
{ }
};
Upvotes: 5