Why cannot I privately derive a class from both a class and another class that the class being derived from uses as a base. So, I have the the following
class Money
{
public:
void get() {std::cin >> amount;}
private:
float amount;
}
class Employee
{
public:
void get() {std::cin >> lastName;}
private:
std::string lastName;
}
class Manager : public Employee, private Money //money is used to store a wage
{
public:
void get() {Employee::get(); Money::get();}
}
class Executive : public Manager, private Money // money is used to store additional bonuses
//warning :direct base 'Money' inaccessible in 'Executive' due to ambiguity
{
public:
void get() {Manager::get(); Money::get();}
}
I expected that in the Executive
class Manager::get()
would invoke Money::get()
to save a wage, while the other Money::get()
would save the additional bonuses.
As far as I know for now, private inheritance may be applied as a form of composition or when the base's interface should be hidden from outsiders, but is useful in implementing the class being derived. I undestand that in this particular case composition is all I need, still, I cannot understand what kind of ambiguity the compiler warns me about, for private inheritance does not allow neither outside classes nor subclasses of a privately derived class to take advantage of the relation
When you inherit from a class in C++, it means that your class contains that base as a subclass (e.g.
Money
), with all of its members. When a derived class of that derived class inherits fromMoney
again, it won't reuse that subclass, but get its own. What happens is:The problem is that
Executive
now has two instances ofMoney
in its class hierarchy:Executive::Money
Executive::Manager::Money
This is the ambiguity that the compiler is warning you about.
Solution A - Composition over inheritance
If you really think about, it makes no sense that a
Manager
inherits fromMoney
, because that would imply that aManager
is an instance ofMoney
. It would make a lot more sense if aManager
hadMoney
:Because
Manager::money
is aprotected
data member, a derived class such asExecutive
will be able to use it.Solution B -
protected
inheritanceDISCLAIMER: DON'T USE INHERITANCE HERE, IT'S CLEARLY WRONG. BUT IF YOU DESPERATELY INSISTED ON IT, HERE IS THE SOLUTION:
The most practical solution is to use
protected
inheritance instead. The outside world still won't have access toMoney
, butExecutive
will: