Pourquoi une fonction virtuelle serait-elle privée?
Je viens de repérer cela dans un code:
class Foo {
[...]
private:
virtual void Bar() = 0;
[...]
}
Est-ce que cela a un but?
(j'essaie de porter du code de VS vers G++, et cela a attiré mon attention)
8 réponses
C'est une fonction virtuelle pure qui se trouve être privé. Cela fait en sorte qu'une classe dérivée doit implémenter la méthode. Dans ce cas, Bar.
Je pense que vous pouvez être confus b / c ceci est fait pour créer des "interfaces" en C++ et beaucoup de fois les gens pensent à ceux-ci comme public. Il y a des cas où vous voudrez peut-être définir une interface privée où une méthode publique utilise ces méthodes privées afin d'assurer l'ordre dans lequel elles sont appelées. (Je crois que c'est appelé le Méthode Modèle)
Pour un exemple relativement mauvais:)
class RecordFile { public: RecordFile(const std::string &filename); void process(const Record &rec) { // Call the derived class function to filter out // records the derived instance of this class does // not care about if (filterRecord(rec)) { writeRecordToFile(rec); } }; private: // Returns true if the record is of importance // and should be kept virtual bool filterRecord(const Record &rec) = 0; void writeRecordToFile(const Record &rec); };
ISO C++ 2003 l'autorise explicitement:
§10.3 n'indique rien sur le spécificateur d'accès et contient même une note de bas de page dans la deuxième clause indiquant dans le contexte des remplacements de fonctions virtuelles:
[...] Le contrôle d'accès (clause 11) est non pris en compte dans la détermination primordial.
Le code est entièrement légal.
La réponse "académique" habituelle est: les spécificateurs d'accès et la virtualité sont orthogonaux - l'un n'affecte pas l'autre.
Une réponse un peu plus pratique: les fonctions virtuelles privées sont souvent utilisées pour implémenter la méthode template Design pattern. Dans les langages qui ne prennent pas en charge les fonctions virtuelles privées, la méthode template doit être publique bien qu'elle ne soit pas vraiment destinée à faire partie de l'interface.
Je vais citer une brève explication du Grand C++ FAQ Lite qui résume bien:
[23.4] quand quelqu'un devrait-il utiliser private virtuals?
Presque jamais.
Les virtuals protégés sont corrects, mais les virtuals privés sont généralement un réseau perte. Raison: les virtuals privés confondent nouveaux programmeurs C++, et confusion augmente les coûts, le calendrier des retards et se dégrade de risque.
Les nouveaux programmeurs C++ sont confus par privé virtuals parce qu'ils pensent un le virtuel privé ne peut pas être remplacé. Après tout, une classe dérivée ne peut pas accès aux membres qui sont privés dans son classe de base donc comment, demandent-ils, pourrait-il remplacer un virtuel privé de son classe de base? Il y a des explications pour ce qui précède, mais c'est académique. Le vrai problème est que presque tout le monde confond la première fois qu'ils exécutent dans virtuals privés, et la confusion est mauvais.
Sauf s'il y a une raison impérieuse de au contraire, à éviter privé virtuals.
Le C++ FAQ Lite a été mis à jour entre-temps:
En passant, il confond la plupart des programmeurs C++ novices que les virtuals privés peuvent être remplacés, et encore moins sont valides du tout. On nous a tous appris que les membres privés d'une classe de base ne sont pas accessibles dans les classes qui en découlent, ce qui est exact. Cependant, cette inaccessibilité par la classe dérivée n'a rien à voir avec le virtuel mécanisme d'appel, qui est à la classe dérivée. Depuis cela pourrait dérouter les novices, la FAQ C++ recommandait autrefois d'utiliser des virtuals protégés plutôt que des virtuals privés. Cependant, l'approche virtuelle privée est maintenant assez courante pour que la confusion des novices soit moins préoccupante.
C'est une fonction virtuelle pure. Toute implémentation finale issue de " Foo "doit implémenter la fonction "Bar".
Cela rend la fonction pure virtuelle par opposition à virtuelle.
Aucune implémentation n'est fournie par défaut et l'intention est que l'implémentation de la fonction doit être spécifiée par une classe d'héritage. Cela peut cependant être remplacé.
Vous voyez parfois des classes complètes où toutes les fonctions membres sont spécifiées comme virtuelles pures de cette manière.
Ce sont des Classes de Base abstraites, parfois appelées classes D'Interface, et le concepteur de L'ABC vous dit: "Je j'ai maintenant une idée de la façon dont cette fonctionnalité serait implémentée pour toutes les spécialisations de cette classe de base. Mais, vous devez avoir tout cela défini pour que votre spécialisation fonctionne et vous savez comment votre objet doit se comporter".
Edit: Oups, juste repéré le fait que la fonction virtuelle pure membre est privée. (Merci Michael) cela change légèrement les choses.
Lorsque cette classe de base est héritée en utilisant l'héritage privé, elle change les choses. Fondamentalement ce que le concepteur de l' la classe de base est en train de dire que, lorsque votre classe dérivée appelle une fonction non privée dans la classe de base. une partie du comportement a été déléguée à votre spécialisation de la fonction dans votre classe dérivée. Le membre non privé fait "quelque chose" et une partie de ce "quelque chose" est un appel, via la fonction pure virtual Base class, à votre implémentation.
Donc, une fonction publique dans Foo appelle la fonction Bar dans Foo, et elle s'appuie sur le fait que vous fournirez une implémentation spécialisée de la fonction Bar pour votre cas particulier.
Scott Meyers se réfère à cela comme"mis en œuvre en termes de".
BTW juste en riant sur le nombre de réponses qui ont été rapidement supprimées par des personnes qui n'ont pas non plus vu les "petits caractères" dans la question! (-:
HTH
Santé,
Le seul but qu'il semble servir est de fournir une interface commune.
BTW même si une fonction est déclarée comme virtuelle privée, elle peut toujours être implémentée et appelée avec l'instance de classe ou à partir d'amis.
Néanmoins, ce genre de choses est généralement destiné à servir d'interface, mais je ne le fais pas de cette façon.