Partilhar via


Herança única

Em "herança única", uma forma comum de herança, classes têm apenas uma classe base.Considere a relação ilustrada na figura a seguir.

Gráfico de herança simples simples

Gráfico de Single_Inheritance simples

Observe a progressão do geral para específico na figura.Outro atributo comum encontrado no projeto da maioria das hierarquias de classe é que a classe derivada tem um "tipo de" relacionamento com a classe base.Na figura, um Book é uma espécie de um PrintedDocumente um PaperbackBook é uma espécie de um book.

Um outro item da nota na Figura: Book é uma classe derivada (de PrintedDocument) e uma classe base (PaperbackBook é derivada de Book).Uma declaração de esqueleto de uma hierarquia de classes é mostrada no exemplo a seguir:

// deriv_SingleInheritance.cpp
// compile with: /LD
class PrintedDocument {};

// Book is derived from PrintedDocument.
class Book : public PrintedDocument {};

// PaperbackBook is derived from Book.
class PaperbackBook : public Book {};

PrintedDocumenté considerada uma classe de "base direto" para Book; ele é uma classe de "base indireto" para PaperbackBook.A diferença é que uma classe base direta aparece na lista de uma declaração de classe base e não uma base indireta.

A classe base da qual deriva-se cada classe é declarada antes da declaração da classe derivada.Não é suficiente fornecer uma declaração com a referência direta para uma classe base; ele deve ser uma declaração completa.

No exemplo anterior, o especificador de acesso pública é usado.O significado de herança público, particular e protegido é descrito em controle de acesso de membro.

Uma classe pode servir como a classe base para muitas classes específicas, conforme ilustrado na figura a seguir.

Amostra de gráfico acíclica direcionado

Exemplo de gráfico acíclico direcionado

No diagrama acima, chamado um "Acíclico gráfico direcionado" (ou "DAG"), algumas das classes são classes base para mais de uma classe derivada.No entanto, a recíproca não é verdadeira: há somente uma classe base direta para qualquer dado o classe derivada.O gráfico na figura ilustra uma estrutura de "herança única".

ObservaçãoObservação

Gráficos Acíclico direcionados não são exclusivos a herança única.Eles também são usados para descrever a herança de múltiplos gráficos.Este tópico é abordado em Herança múltipla.

Em herança, a classe derivada contém os membros da classe base mais quaisquer novos membros que você adiciona.Como resultado, uma classe derivada pode se referir aos membros da classe base (a menos que esses membros são redefinidos na classe derivada).O operador de escopo de resolução (::) pode ser usado para se referir a membros de classes base diretas ou indiretas quando esses membros têm foi redefinidos na classe derivada.Considere este exemplo:

// deriv_SingleInheritance2.cpp
// compile with: /EHsc /c
#include <iostream>
using namespace std;
class Document {
public:
   char *Name;   // Document name.
   void PrintNameOf();   // Print name.
};

// Implementation of PrintNameOf function from class Document.
void Document::PrintNameOf() {
   cout << Name << endl;
}

class Book : public Document {
public:
   Book( char *name, long pagecount );
private:
   long  PageCount;
};

// Constructor from class Book.
Book::Book( char *name, long pagecount ) {
   Name = new char[ strlen( name ) + 1 ];
   strcpy_s( Name, strlen(Name), name );
   PageCount = pagecount;
};

Observe que o construtor para Book, (Book::Book), tem acesso ao membro de dados, Name.Em um programa, um objeto do tipo Book podem ser criados e usados da seguinte maneira:

//  Create a new object of type Book. This invokes the
//   constructor Book::Book.
Book LibraryBook( "Programming Windows, 2nd Ed", 944 );

...

//  Use PrintNameOf function inherited from class Document.
LibraryBook.PrintNameOf();

Como o exemplo anterior demonstra, membro de classe e dados herdados e funções são usadas idêntico.Se a implementação de classe Book chama a reimplementação da PrintNameOf função, a função que pertence a Document classe pode ser chamado apenas usando a resolução de escopo (::) operador:

// deriv_SingleInheritance3.cpp
// compile with: /EHsc /LD
#include <iostream>
using namespace std;

class Document {
public:
   char *Name;          // Document name.
   void  PrintNameOf() {}  // Print name.
};

class Book : public Document {
   Book( char *name, long pagecount );
   void PrintNameOf();
   long  PageCount;
};

void Book::PrintNameOf() {
   cout << "Name of book: ";
   Document::PrintNameOf();
}

Ponteiros e referências a classes derivadas podem ser implicitamente convertidas em ponteiros e referências a suas classes base se houver uma classe base acessível e objetiva.O código a seguir demonstra esse conceito usando ponteiros (o mesmo princípio se aplica às referências):

// deriv_SingleInheritance4.cpp
// compile with: /W3
struct Document {
   char *Name;
   void PrintNameOf() {}
};

class PaperbackBook : public Document {};

int main() {
   Document * DocLib[10];   // Library of ten documents.
   for (int i = 0 ; i < 10 ; i++)
      DocLib[i] = new Document;
}

No exemplo anterior, os diferentes tipos são criados.No entanto, porque esses tipos são derivados da Document da classe, há uma conversão implícita para Document *.Como resultado, DocLib é uma "lista heterogênea" (uma lista no qual não todos os objetos são do mesmo tipo) que contém diferentes tipos de objetos.

Porque o Document classe tem um PrintNameOf função, ele pode imprimir o nome de cada livro na biblioteca, embora ele pode omitir algumas informações específicas ao tipo de documento (página contagem para Book, o número de bytes para HelpFilee assim por diante).

ObservaçãoObservação

Forçando a classe base para implementar uma função, como PrintNameOf não é geralmente o melhor design.Funções virtuais oferece outras alternativas de design.

Consulte também

Referência

Visão geral de Classes derivadas

Herança múltipla