Reputation: 526
I've encountered the following situation in my C++ code (this is an example to illustrate the problem, and has not much to do with the actual code). I have a virtual class Family
and two classes that I derive from it:
class Family {
public:
virtual double operator()(double const & x) const = 0;
virtual ~Family();
};
class Mother : public Family {
public:
double operator()(double const & x) const override { return x*x; }
};
class Father : public Family {
public:
double operator()(double const & x) const override { return x-2; }
};
Then I have another class Car
. This class should have a private member that can be either an object from the Mother
or Father
class. I tried to implement this as
class Car {
public:
Car(Family member) : right_seat_(member) {}
private:
Family right_seat_;
};
If one tries to run the above via the main function
int main(){
Mother lucy = Mother();
Car Van = Car(lucy);
}
I get the error that member
in the constructor of Car
cannot be declared since Family
is abstract. I understand the problem and why this happens, but I don't know what the right tool in C++ is to solve the problem. Unfortunately I also don't know how to google this properly (I didn't really find any suitable suggestions).
The only idea that I had was to remove the abstract class altogether and template the Car
class. I'd like to avoid this, since in the original problem the two derived classes logically belong to a "superclass", so I don't want to introduce this split if it is not absolutely necessary.
Upvotes: 0
Views: 76
Reputation: 530
You need to use references or pointers for polymorphism. One possible solution would be:
class Car {
public:
Car(Family* member) : right_seat_(member) {}
private:
Family* right_seat_;
};
int main(){
Mother* lucy = new Mother();
Car Van = Car(lucy);
...//do stuff with car
}
Don't forget to delete
the pointers once you are done with them.
If you can use c++11 (c++14 for std::make_unique) or higher, using smart-pointers is even better:
class Car {
public:
Car(std::unique_ptr<Family>&& member) : right_seat_(std::move(member)) {}
private:
std::unique_ptr<Family> right_seat_;
};
int main(){
std::unique_ptr<Family> lucy = std::make_unique<Mother>();
Car Van = Car(std:move(lucy));
...//do stuff with car
}
Upvotes: 2
Reputation: 238311
Abstract classes cannot be members because they cannot be instantiated.
Dynamic polymorphism requires indirection. What you can have is a pointer to an abstract base.
This class should have a private member that can be either an object from the Mother or Father class.
A variable in C++ cannot have sometimes one type and other times another type. There is exactly on type for every variable except within templates where different instances of a template can have different types.
Again, this is where you need indirection: You can have a pointer that points to a base, and it doesn't matter which derived class contains that base.
If you want Car
to own (i.e. control and be responsible for the lifetime of) the indirectly referred family as it would own a member, then you need to use dynamic allocation. That said, such ownership relationship seems dubious from design perspective.
Upvotes: 1