Лучшая модель наследования:
/–––––––––– Cat
/ /
/ Runner
/ \
Animal –––––––––––––– Dog
\ /
\ Swimmer
\ \
\–––––––––– Dolphin
Вы избегаете ромбов, которые вы использовали в своем подходе.
Вместо наследования вы можете вместо этого агрегировать экземпляр Runner
/ Swimmer
внутри животных, где это необходимо, и позволить функциям животных просто делегировать членам.
Просто небольшая проблема, касающаяся вашей модели: на самом деле это не отражает реальность, на самом деле, кошки, хотя и не любят воду, тоже неплохие пловцы ...
Редактировать: Поскольку Runner
и Swimmer
требуется доступ к Animal
участникам: вы можете предоставить это через любопытно повторяющийся шаблон ; добавил демонстрацию ниже:
class Animal
{
protected:
int n = 7;
};
template <typename T>
class Swimmer
{
public:
void swim()
{
std::cout << static_cast<T*>(this)->n << std::endl;
}
};
class Dolphin : public Animal, public Swimmer<Dolphin>
{
friend class Swimmer; // n is protected!
// (alternatively, Swimmer might already be a friend of Animal)
};
int main(int argc, char* argv[])
{
Dolphin d;
d.swim();
return 0;
}