Herança múltipla em C ++

Se uma classe C ++ pode herdar de outro, então surge a questão imediatamente ", uma classe pode herdar de duas (ou mais) aulas?" O em resposta é um incondicional "sim".

Pode ser útil para ver um exemplo do mundo real de herança múltipla entender por que isso é uma capacidade vale a pena ter. A maioria das universidades oferecem empregos para estudantes de graduação como assistentes de ensino. Estes indivíduos são ainda estudantes e tem todas as propriedades de um aluno - mas, além disso, eles também são oferecidas as características de um instrutor. Assim, logicamente, a sua árvore de herança parece com isso:

A & lt; span class =TeachingAssistant herda de ambos Aluna "/>
UMA Professor assistente herda de ambos Aluna e Instrutor.

Expressa em C ++, isso iria aparecer da seguinte forma:

classe Student {public: GPA double () - bool se inscrever (Curso) pay -bool (dólares duplas) -} - classe instrutor {public: grau duplo (Artefato) -bool ensinar (claro) -bool GetPaid (dólares duplos) -} TeachingAssistant de classe: Estudante pública, Instrutor pública {public: conselheiro Instructor (Instrutor) -Instructor conselheiro () -} -

A única diferença entre este exemplo e exemplos de herança simples, é o aparecimento de dois nomes de classe após a declaração de Professor assistente.

Dadas as definições de classe apenas mostrados, todos os seguintes podem ser ditas:

TeachingAssistant ta - // obter um grau como um d studentdouble = ta.gpa () - // grau um papel como um instructorta.grade (documento) - // posso passar uma ta para uma função que espera uma festa Studentvoid (Student ) -party (ta) - // ou uma função que espera um sarau Instructorvoid (Instrutor) -soiree (ta) -

Por enquanto, tudo bem. O que há para não gostar sobre a herança múltipla?

vários ambiguidades

Revendo Aluna e Instrutor aulas, essas duas classes de acções de uma propriedade: um número de identificação atribuído pelo universidade. Mas se você tentar adicionar esta propriedade da seguinte forma, você não ganha nada, mas as queixas de C ++:

classe Student {public: IntID () - double GPA () - bool se inscrever (Curso) pay -bool (dólares duplas) -} - classe instrutor {public: int id () - duplo grau (Artefato) -bool ensinar (Curso) -bool GetPaid (dólares duplas) -} - classe TeachingAssistant: Estudante pública, Instrutor pública {public: conselheiro Instructor (Instrutor) -Instructor conselheiro () -

};

Este problema é mostrado graficamente, aqui:

Adicionando o & lt; span class =id () propriedade para ambos Aluna e
adicionando o identidade() propriedade para ambos Aluna e Instrutor causa confusão.

O problema é que agora, quando você diz algo como

TeachingAssistant ta-cout lt; lt; "ID do TA é" lt; lt; ta.id () - // que id?

qual identidade() destina-se - o que um Professor assistente herda de Aluna ou o que ele herda de Instrutor? A ambiguidade pode ser resolvida especificando o caminho para identidade (Conhecido como nome qualificado) como isso:

cout lt; lt; "TA ID de estudante é" lt; lt; ta.Student :: id () -

Agora não há nenhuma ambiguidade. Ao especificar a classe base, C ++ é dito que identidade() escolher.

Resolver a ambigüidade: Primeira tentativa

Mas e se as duas instâncias de identidade() estamos não diferente? Suponha que, como muitas universidades, uma universidade particular, atribui um número de identificação único para os alunos e instrutores. Nesse caso, o que está realmente queria é a situação mostrada na imagem a seguir: Agora, um Professor assistente mas tem uma única identidade() propriedade.

A & lt; span class =id () Propriedade é herdado de uma classe base comum a ambos
o identidade() propriedade é herdada de uma classe base comum a ambos Aluna e Instrutor.

Para tentar expressar esse estado de coisas em C ++, suponha que o seguinte está escrito:

classe Academic {public: int id () -} - classe Student: Academic pública {public: GPA double () - bool se inscrever (Curso) pay -bool (dólares duplas) -} - instrutor de classe: Academic pública {public: grau de casal (Artefato) -bool ensinar (Curso) -bool GetPaid (dólares duplas) -} - classe TeachingAssistant: Estudante pública, Instrutor pública {public: Instrutor conselheiro (Instrutor) -Instructor conselheiro () -} -

Infelizmente (e surpreendentemente), esta abordagem não resolve o problema. Uma referência a ta.id () ainda é ambígua. Acontece que este código não cria a imagem-anterior em vez disso, ele cria a situação mostrada aqui:

A classe base única pode ser herdada na subclasse várias vezes.
A classe base única pode ser herdada na subclasse várias vezes.

Parece que Professor assistente agora herda acadêmico duas vezes - uma vez através da sua Aluna-Ness, e mais uma vez através da sua Instrutor-ness. Tem agora um Estudante :: Academic id :: () e um Instrutor :: Academic id :: ().

Resolver a ambigüidade

A fim de alcançar o que aparece na terceira figura deste artigo em C ++, você deve voltar a cair chamadas algo C ++ herança virtual. Esta característica aparece em ação como se segue:

classe TeachingAssistant: Estudante pública virtual, instrutor público virtual {public: conselheiro Instructor (Instrutor) -Instructor conselheiro () -} -

O uso do virtual palavra-chave diz C ++ para combinar qualquer base de classes comuns que Aluna e Instrutor pode compartilhar. O que se segue não gera um erro do compilador:

cout lt; lt; "TA ID de estudante é" lt; lt; ta.id () - // nenhum erro agora

Com a herança virtual, Professor assistente herda uma e apenas uma cópia do acadêmico ea referência a ta.id () não é ambígua.

menu