Une virtual
fonction pure doit être implémentée dans un type dérivé qui sera directement instancié, mais le type de base peut toujours définir une implémentation. Une classe dérivée peut appeler explicitement l'implémentation de la classe de base (si les autorisations d'accès le permettent) en utilisant un nom complet (en appelant A::f()
dans votre exemple - si l' A::f()
était public
ou protected
). Quelque chose comme:
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
Le cas d'utilisation auquel je peux penser du haut de ma tête est celui où il existe un comportement par défaut plus ou moins raisonnable, mais le concepteur de classe souhaite que ce comportement par défaut ne soit invoqué qu'explicitement. Il peut également être le cas dans lequel vous souhaitez que les classes dérivées effectuent toujours leur propre travail mais soient également capables d'appeler un ensemble commun de fonctionnalités.
Notez que même si cela est permis par le langage, ce n'est pas quelque chose que je vois couramment utilisé (et le fait que cela puisse être fait semble surprendre la plupart des programmeurs C ++, même les plus expérimentés).
deported
. (soit dans un .inl ou .cpp pour faire référence aux pratiques courantes de dénomination des fichiers).Pour être clair, vous ne comprenez pas ce que = 0; après une fonction virtuelle signifie.
= 0 signifie que les classes dérivées doivent fournir une implémentation, pas que la classe de base ne puisse pas fournir une implémentation.
En pratique, lorsque vous marquez une fonction virtuelle comme pure (= 0), il est très peu utile de fournir une définition, car elle ne sera jamais appelée à moins que quelqu'un ne le fasse explicitement via Base :: Function (...) ou si le Le constructeur de classe de base appelle la fonction virtuelle en question.
la source
L'avantage est qu'il oblige les types dérivés à toujours remplacer la méthode, mais fournit également une implémentation par défaut ou additive.
la source
Si vous avez du code qui devrait être exécuté par la classe dérivée, mais que vous ne voulez pas qu'il soit exécuté directement - et que vous voulez le forcer à être remplacé.
Votre code est correct, bien que dans l'ensemble ce ne soit pas une fonctionnalité souvent utilisée, et généralement visible uniquement lorsque vous essayez de définir un destructeur virtuel pur - dans ce cas, vous devez fournir une implémentation. Ce qui est drôle, c'est qu'une fois que vous dérivez de cette classe, vous n'avez pas besoin de remplacer le destructeur.
Par conséquent, la seule utilisation sensée des fonctions virtuelles pures est de spécifier un destructeur virtuel pur comme un mot clé "non final".
Le code suivant est étonnamment correct:
la source
Il faudrait donner un corps à un pur destructeur virtuel, par exemple :)
Lire: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/
(Lien cassé, utiliser l'archive)
la source
Oui, c'est correct. Dans votre exemple, les classes qui dérivent de A héritent à la fois de l'interface f () et d'une implémentation par défaut. Mais vous forcez les classes dérivées à implémenter la méthode f () (même si ce n'est que pour appeler l'implémentation par défaut fournie par A).
Scott Meyers en parle dans Effective C ++ (2e édition) Item # 36 Différencier l'héritage de l'interface et l'héritage de l'implémentation. Le numéro d'article peut avoir changé dans la dernière édition.
la source
Les fonctions virtuelles pures avec ou sans corps signifient simplement que les types dérivés doivent fournir leur propre implémentation.
Les corps de fonction virtuelle purs dans la classe de base sont utiles si vos classes dérivées veulent appeler votre implémentation de classe de base.
la source
Le 'virtual void foo () = 0;' La syntaxe ne signifie pas que vous ne pouvez pas implémenter foo () dans la classe actuelle, vous pouvez. Cela ne signifie pas non plus que vous devez l'implémenter dans des classes dérivées . Avant de me gifler, observons le problème du diamant: (code implicite, remarquez).
Maintenant, l'invocation obj-> foo () aboutira à B :: foo () puis à C :: bar ().
Vous voyez ... les méthodes virtuelles pures n'ont pas besoin d'être implémentées dans des classes dérivées (foo () n'a pas d'implémentation dans la classe C - le compilateur compilera) En C ++, il y a beaucoup de failles.
J'espère que je pourrais aider :-)
la source
C
dans votre exemple. Vous pouvez instancier un objet de typeD
parce qu'il obtient sa mise en œuvre àfoo
partirB
.Un cas d'utilisation important d' une méthode virtuelle pure avec un corps d'implémentation , est lorsque vous voulez avoir une classe abstraite, mais que vous n'avez aucune méthode appropriée dans la classe pour la rendre purement virtuelle. Dans ce cas, vous pouvez rendre le destructeur de la classe purement virtuel et mettre l'implémentation souhaitée (même un corps vide) pour cela. Par exemple:
Cette technique rend la
Foo
classe abstraite et par conséquent impossible d'instancier la classe directement. En même temps, vous n'avez pas ajouté de méthode virtuelle pure supplémentaire pour rendre laFoo
classe abstraite.la source