Em C ++, uma classe pode herdar (direta ou indiretamente) de mais de uma classe, o que é conhecido como
herança múltipla .
C # e Java, entretanto, limitam as classes à herança única que cada classe herda de uma única classe pai.
A herança múltipla é uma maneira útil de criar classes que combinam aspectos de duas hierarquias de classes distintas, algo que geralmente acontece ao usar diferentes estruturas de classe em um único aplicativo.
Se duas estruturas definem suas próprias classes de base para exceções, por exemplo, você pode usar herança múltipla para criar classes de exceção que podem ser usadas com qualquer estrutura.
O problema com a herança múltipla é que ela pode levar à ambiguidade. O exemplo clássico é quando uma classe herda de duas outras classes, cada uma das quais herda da mesma classe:
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
}
};
Neste exemplo, o flag
membro de dados é definido por class A
. Mas class D
descende de class B
e class C
, de que ambos derivam A
, então, em essência, duas cópias de flag
estão disponíveis porque duas instâncias de A
estão na D
hierarquia de classes de. Qual você deseja definir? O compilador reclamará que a referência a flag
in D
é ambígua . Uma correção é eliminar a ambiguidade da referência explicitamente:
B::flag = nflag;
Outra correção é declarar B e C como virtual base classes
, o que significa que apenas uma cópia de A pode existir na hierarquia, eliminando qualquer ambigüidade.
Outras complexidades existem com herança múltipla, como a ordem em que as classes básicas são inicializadas quando um objeto derivado é construído ou a maneira como os membros podem ser inadvertidamente ocultados das classes derivadas. Para evitar essas complexidades, algumas linguagens se restringem ao modelo mais simples de herança única.
Embora isso simplifique consideravelmente a herança, também limita sua utilidade porque apenas classes com um ancestral comum podem compartilhar comportamentos. As interfaces atenuam um pouco essa restrição, permitindo que classes em diferentes hierarquias exponham interfaces comuns, mesmo que não sejam implementadas por meio do compartilhamento de código.