В C ++ класс может наследовать (прямо или косвенно) от более чем одного класса, который называется
множественное наследование .
C # и Java, однако, ограничивают классы одиночным наследованием каждый класс наследует
из одного родительского класса.
Множественное наследование - это полезный способ создания классов, объединяющих аспекты двух разнородных классов.
иерархии, что часто случается при использовании различных классов классов в рамках одного
приложение.
Если, например, две структуры определяют свои собственные базовые классы для исключений, вы можете
использовать множественное наследование для создания классов исключений, которые можно использовать с любой платформой.
Проблема множественного наследования заключается в том, что оно может привести к неоднозначности. Классический пример - это когда
класс наследуется от двух других классов, каждый из которых наследуется от того же класса:
class A {
protected:
bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
public:
void setFlag( bool nflag ){
flag = nflag; // ambiguous
}
};
В этом примере элемент данных flag
определяется как class A
. Но class D
происходит от class B
и class C
, которые оба происходят от A
, поэтому по сути две копии из flag
доступны, потому что
экземпляры A
находятся в иерархии классов D
. Какой из них вы хотите установить? Компилятор будет жаловаться
что ссылка на flag
в D
является неоднозначной . Одним из исправлений является явное устранение неоднозначности ссылки:
B::flag = nflag;
Другим исправлением является объявление B и C как virtual base classes
, что означает, что только одна копия A может
существуют в иерархии, устраняя любую неопределенность.
Существуют другие сложности с множественным наследованием, такие как порядок, в котором базовые классы
инициализируется при создании производного объекта или способе непреднамеренного скрытия членов
из производных классов. Чтобы избежать этих сложностей, некоторые языки ограничиваются более простой моделью одиночного наследования.
Хотя это значительно упрощает наследование, оно также ограничивает его полезность
потому что только классы с общим предком могут делиться поведением. Интерфейсы смягчают это
ограничение, позволяя классам в разных иерархиях выставлять общие интерфейсы даже
если они не реализованы путем совместного использования кода.