Premièrement : souligner un concept

Définir une fonction comme virtuelle ne signifie pas que la fonction n'est pas implémentée.

Le définir comme virtuel permet d'utiliser un pointeur de classe de base pour appeler cette fonction de la classe dérivée.

Définir une fonction comme fonction virtuelle pure signifie seulement que la fonction n'est pas implémentée.

Définir une fonction virtuelle pure consiste à implémenter une interface, servant de spécification, spécifiant que les programmeurs qui héritent de cette classe doivent implémenter cette fonction.

1. Introduction

Supposons que nous ayons la hiérarchie de classes suivante :

Exemple

class A { public:     virtual void foo()     {         cout<<"A::foo() est appelée"<<endl;     } }; class B:public A { public:     void foo()     {         cout<<"B::foo() est appelée"<<endl;     } }; int main(void) {     A *a = new B();     a->foo();   // Ici, bien que a soit un pointeur vers A, la fonction appelée (foo) est celle de B !     return 0; }

Cet exemple est une application typique des fonctions virtuelles. À travers cet exemple, vous acquerrez peut-être une certaine notion des fonctions virtuelles. Elle est virtuelle dans ce qu'on appelle la « liaison tardive » ou la « liaison dynamique » : l'appel à une fonction de classe n'est pas déterminé à la compilation, mais à l'exécution. Comme, lors de l'écriture du code, on ne peut pas déterminer si la fonction appelée est celle de la classe de base ou celle de quelle classe dérivée, on l'appelle une fonction « virtuelle ».

Les fonctions virtuelles ne peuvent réaliser le polymorphisme qu'à l'aide de pointeurs ou de références.


Fonctions virtuelles pures en C++

1. Définition

 

Une fonction virtuelle pure est une fonction virtuelle déclarée dans la classe de base. Elle n'a pas de définition dans la classe de base, mais exige que toute classe dérivée définisse sa propre méthode d'implémentation. La façon d'implémenter une fonction virtuelle pure dans la classe de base est d'ajouter après le prototype de la fonction=0:

 
virtual void funtion1()=0

2. Raisons de l'introduction

  

1. Pour utiliser commodément les fonctionnalités de polymorphisme, nous avons souvent besoin de définir des fonctions virtuelles dans la classe de base.

  

2. Dans de nombreux cas, il n'est pas raisonnable que la classe de base elle-même génère des objets. Par exemple, un animal en tant que classe de base peut dériver des sous-classes telles que le tigre et le paon, mais générer un objet à partir de l'animal lui-même est manifestement déraisonnable.

  

Pour résoudre les problèmes ci-dessus, le concept de fonctions virtuelles pures est introduit, et la fonction est définie comme une fonction virtuelle pure (méthode :virtual ReturnType Function()= 0;), alors le compilateur exige qu'elle soit redéfinie dans les classes dérivées pour réaliser le polymorphisme. En même temps, une classe contenant des fonctions virtuelles pures est appelée classe abstraite, qui ne peut pas générer d'objets. Cela résout bien les deux problèmes ci-dessus.

Une classe qui déclare une fonction virtuelle pure est une classe abstraite. Par conséquent, les utilisateurs ne peuvent pas créer d'instances de la classe, mais uniquement créer des instances de ses classes dérivées.

La caractéristique la plus notable des fonctions virtuelles pures est: elles doivent redéclarer la fonction dans la classe qui hérite (ne pas inclure le =0 suivant, sinon la classe dérivée ne peut pas non plus être instanciée), et elles n'ont souvent aucune définition dans la classe abstraite.

Le but de définir des fonctions virtuelles pures est de faire en sorte que les classes dérivées n'héritent que de l'interface de la fonction.

La signification des fonctions virtuelles pures est de permettre à tous les objets de classe (principalement les objets de classes dérivées) d'effectuer les actions de la fonction virtuelle pure, mais la classe ne peut pas fournir d'implémentation par défaut raisonnable pour la fonction virtuelle pure. Par conséquent, la déclaration d'une fonction virtuelle pure dans une classe dit aux concepteurs des sous-classes : « Vous devez fournir une implémentation de la fonction virtuelle pure, mais je ne sais pas comment vous l'implémenterez. »


Introduction aux classes abstraites

Une classe abstraite est une classe spéciale établie à des fins d'abstraction et de conception. Elle se situe à un niveau supérieur de la hiérarchie d'héritage.

(1) Définition d'une classe abstraite :Une classe comportant des fonctions virtuelles pures est appelée classe abstraite.

(2) Rôle d'une classe abstraite :Le rôle principal d'une classe abstraite est d'organiser des opérations liées en tant qu'interfaces dans une hiérarchie d'héritage, afin de fournir une racine commune aux classes dérivées. Les classes dérivées implémentent concrètement les opérations qui servent d'interfaces dans leur classe de base. Par conséquent, une classe dérivée décrit en fait la sémantique commune d'un groupe d'interfaces d'opérations de sous-classes. Ces sémantiques sont également transmises aux sous-classes, qui peuvent les implémenter concrètement ou les transmettre à leurs propres sous-classes.

(3) Remarques lors de l'utilisation de classes abstraites :

  • Une classe abstraite ne peut être utilisée que comme classe de base, et ses fonctions virtuelles pures sont implémentées par les classes dérivées. Si une classe dérivée ne redéfinit pas les fonctions virtuelles pures mais hérite uniquement des fonctions virtuelles pures de la classe de base, alors cette classe dérivée reste une classe abstraite. Si une classe dérivée fournit des implémentations pour les fonctions virtuelles pures de la classe de base, alors cette classe dérivée n'est plus une classe abstraite ; c'est une classe concrète à partir de laquelle des objets peuvent être créés.
  • Les classes abstraites ne peuvent pas définir d'objets.

Résumé :

  • 1. Une fonction virtuelle pure est déclarée comme suit :virtual void funtion1()=0;Une fonction virtuelle pure n'a nécessairement aucune définition. Les fonctions virtuelles pures servent à standardiser le comportement des classes dérivées, c'est-à-dire l'interface. Une classe contenant des fonctions virtuelles pures est une classe abstraite. Une classe abstraite ne peut pas définir d'instances, mais des pointeurs ou des références vers des classes concrètes qui implémentent la classe abstraite peuvent être déclarés.

  • 2. Une fonction virtuelle est déclarée comme suit :virtual ReturnType FunctionName(Parameter)Une fonction virtuelle doit être implémentée. Si elle ne l'est pas, le compilateur signalera une erreur, avec le message d'erreur :

    error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
  • 3. Pour les fonctions virtuelles, la classe parente et la classe enfant ont chacune leur propre version. Lorsqu'elles sont appelées de manière polymorphe, elles sont liées dynamiquement.

  • 4. Dans une sous-classe qui implémente une fonction virtuelle pure, cette fonction virtuelle pure devient une fonction virtuelle dans la sous-classe. La sous-classe de la sous-classe, c'est-à-dire la classe petite-fille, peut redéfinir cette fonction virtuelle, et elle est liée dynamiquement lorsqu'elle est appelée de manière polymorphe.

  • 5. Les fonctions virtuelles sont le mécanisme en C++ utilisé pour implémenter le polymorphisme. L'idée centrale est d'accéder aux fonctions définies dans les classes dérivées à travers les classes de base.

  • 6. Lors de l'allocation dynamique de mémoire sur le tas, le destructeur doit être une fonction virtuelle, mais il n'a pas besoin d'être virtuel pur.

  • 7. Les amis ne sont pas des fonctions membres. Seules les fonctions membres peuvent être virtuelles, donc les amis ne peuvent pas être des fonctions virtuelles. Cependant, le problème virtuel des amis peut être résolu en faisant en sorte que les fonctions amies appellent des fonctions membres virtuelles.

  • 8. Le destructeur doit être une fonction virtuelle, afin que le destructeur du type d'objet correspondant soit appelé. Par conséquent, si le pointeur pointe vers un objet de sous-classe, le destructeur de la sous-classe sera appelé, puis le destructeur de la classe de base sera appelé automatiquement.

Une classe avec des fonctions virtuelles pures est une classe abstraite ; elle ne peut pas générer d'objets et ne peut qu'être dérivée. Si les fonctions virtuelles pures de sa classe dérivée n'ont pas été redéfinies, alors sa classe dérivée est toujours une classe abstraite.

Définir des fonctions virtuelles pures sert à rendre la classe de base non instanciable, car instancier une telle structure de données abstraite est en soi dénué de sens, et fournir une implémentation l'est aussi.

En fait, à mon avis personnel, l'introduction des fonctions virtuelles pures a deux objectifs :

  • 1. Pour la sécurité : éviter des résultats inconnus causés par une négligence là où une implémentation explicite est nécessaire, en rappelant aux sous-classes d'implémenter ce qu'elles doivent implémenter.
  • 2. Pour l'efficacité : non pas l'efficacité de l'exécution du programme, mais l'efficacité du codage.

URL d'origine : https://blog.csdn.net/hackbuteer1/article/details/7558868