Partager via


Héritage unique

Dans « l'héritage unique, » un formulaire courant d'héritage, les classes ont une seule classe de base.considérez la relation illustrée dans l'illustration suivante.

Unique-Héritage simple Graphique

Graphique Single_Inheritance Simple

notez la progression du général au détail dans l'illustration.Un autre attribut commun trouvé dans la conception de la plupart des hiérarchies de classes est que la classe dérivée a un « type » de relation avec la classe de base.Dans l'illustration, Book est un type de PrintedDocument, et PaperbackBook est un type de book.

Un autre élément à retenir dans l'illustration : Book est une classe dérivée (d' PrintedDocument) et une classe de base (PaperbackBook est dérivé d' Book).Une déclaration squelette d'une telle hiérarchie de classes est illustrée dans l'exemple suivant :

// 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 est considéré comme une classe « dirigent base » à Book; il s'agit de » une classe de base « indirecte à PaperbackBook.La différence est qu'une classe de base directe s'affiche dans la liste de base d'une déclaration de classe et une base indirecte ne le fait pas.

la classe de base dont chaque classe est dérivée est déclarée avant la déclaration de la classe dérivée.Il ne suffit pas de fournir une déclaration en avant-référençante pour une classe de base ; il doit s'agir d'une déclaration complète.

dans l'exemple précédent, le spécificateur d'accès public est utilisé.la signification du public, protégée, et l'héritage privé est décrite dans Contrôle d'accès de membre.

Une classe peut servir de classe de base à de nombreuses classes spécifiques, comme illustré dans l'illustration suivante.

Exemple de Graphique acyclique dirigé

Exemple de graphique acyclique dirigé

Dans le diagramme ci-dessus, appelé « a exécuté le graphique acyclique » (ou « DAG »), certaines classes sont des classes de base pour plusieurs classe dérivée.Toutefois, l'inverse n'est pas satisfaite : il existe une seule classe de base directe pour toute classe dérivée données.le graphique dans l'illustration représente une structure « d'héritage unique ».

[!REMARQUE]

Les graphiques dirigés acycliques ne sont pas uniques pour choisir l'héritage.ils sont également utilisés pour représenter des graphiques d'héritage multiple.Cette rubrique est décrite à héritage multiple.

Dans l'héritage, la classe dérivée contient les membres de la classe de base et tous les nouveaux membres que vous ajoutez.Par conséquent, une classe dérivée peut faire référence à des membres de la classe de base (à moins que ces membres sont redéfinis dans la classe dérivée).L'opérateur de résolution de portée (::) peut être utilisé pour faire référence à des membres des classes de base directes ou indirectes lorsque ces membres ont été redéfinis dans la classe dérivée.Considérez cet exemple :

// 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;
};

Notez que le constructeur de Book, (Book::Book), vous avez accès aux données membres, Name.dans un programme, un objet de type Book peut être créé et utilisé comme suit :

//  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();

Comme le montre l'exemple précédent, le membre de classe et les données et les fonctions héritées sont utilisés de la même manière.Si l'implémentation pour les appels d' Book de classe pour un reimplementation de la fonction d' PrintNameOf , la fonction qui appartient à la classe d' Document peut être appelée uniquement à l'aide de l'opérateur de résolution de portée (::) :

// 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();
}

Les pointeurs et les références aux classes dérivées peuvent être convertis implicitement aux pointeurs et aux références à leurs classes de base s'il existe une classe de base accessible et non équivoque.Le code suivant illustre ce concept utilisation des pointeurs (le même principe s'applique aux références) :

// 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;
}

Dans l'exemple précédent, les différents types sont créés.Toutefois, ces types sont tous dérivés de la classe d' Document , il existe une conversion implicite à Document *.Par conséquent, DocLib est « une liste hétérogène » (une liste dans laquelle tous les objets sont du même type) contenant plusieurs types d'objets.

Étant donné que la classe d' Document a une fonction d' PrintNameOf , elle peut imprimer le nom de chaque livre dans la bibliothèque, mais elle peut omettre une partie du informations spécifiques au type de document (nombre de pages pour Book, nombre d'octets pour HelpFile, etc.).

[!REMARQUE]

Forcer la classe de base pour implémenter une fonction telle qu' PrintNameOf n'est souvent pas la meilleure conception.fonctions virtuelles offre d'autres éléments de conception.

Voir aussi

Référence

Présentation des classes dérivées

Héritage multiple