Reputation: 35
I'm having a problem initializing a shared_ptr
member of a class I'm working on.
I have two classes, A
and B
:
class A {
int _x;
int _y;
public:
A(int, int);
};
A::A(int x, int y) {
_x = x;
_y = y;
}
class B : public A {
std::shared_ptr<A> _a;
public:
B(std::shared_ptr<A>);
};
B::B(std::shared_ptr<A> a) : _a(a) {}
int main() {
std::shared_ptr<A> a = std::make_shared<A>(1, 2);
B b(a);
return 0;
}
I just want class B
to hold a std::shared_ptr
to an instance of class A
.
However, I'm getting the error no matching function for call to A::A()
in B
's constructor.
I'm confused because I thought the point of the initializer list is to avoid implicitly calling the default constructor for member variables, but it still seems to be trying to call A
's default constructor.
Any explanation is appreciated, thanks.
edit: after more messing around, it seems like it complies properly if B
does not inherit from A
. Still unsure why inheriting from A
results in A
's default constructor being called from B
's constructor.
Upvotes: 2
Views: 801
Reputation: 153
When you call B b(a);
, you construct a B
object using the constructor B::B(std::shared_ptr<A> a)
.
The issue is in your definition of this constructor. B
inherits from A
, meaning that B
is not just a B
, but instead is really an A
and B
stacked on top of each other. A
is the base class, so it is on the bottom. So when you try to construct a B
object, the code must first construct the A
object at the bottom/base to form the foundation for the B
object to exist on. That means that you actually have to tell the code how to construct the A
object.
Because you defined a constructor for A
that takes two int
variables, the compiler does not generate a default constructor for A
. Therefore, you must explicitly write out how A
should be constructed within B
. Constructing the A
object can be done in the initializer list of the B
object's constructor:
B::B(std::shared_ptr<A> a) : A(0,0), _a(a) {}
Upvotes: 2
Reputation: 182763
Since B
is derived from A
, every B
is an A
. That means to construct a B
, you must also construct an A
. However, you do not tell B
's constructor how to construct an A
, so the default constructor is used.
If you want B
to be derived from A
and only hold a shared_ptr
to A
, then A
must not do anything you don't want B
to do. Here, A
has _x
and _y
.
It's not clear what you really want, but perhaps you want some other base class that both A
and B
derive from that only has what both A
and B
should have.
The classic example of inheritance in C++ is something like Instrument
being the base class that has members like Play
with derived classes like Trumpet
and Clarinet
having the thing that makes some particular instrument a trumpet. Only what is common to Trumpet
s and Clarinet
s should be in Instrument
.
Upvotes: 2