Je suis récemment appris à savoir que dans les fonctions virtuelles pure C++ peuvent éventuellement avoir un corps.
Quels sont les cas d'utilisation du monde réel pour de telles fonctions?
Les fonctions virtuelles pures avec ou sans corps signifient simplement que les types dérivés doivent fournir leur propre mise en œuvre.
Les corps de fonction virtuelle pure dans la classe de base sont utiles si vos classes dérivées souhaitent appeler votre implémentation de classe de base.
Une des raisons d'une classe de base abstraite (avec une fonction virtuelle pure) peut fournir une implémentation d'une fonction virtuelle pure qu'il est déclarée consiste à laisser des classes dérivées ont une "valeur par défaut" facile à utiliser. Il n'y a pas beaucoup d'avantage à ce sujet sur une fonction virtuelle normale qui peut être éventuellement remplacée - en fait, la seule différence réelle est que vous forcez la classe dérivée à expliquer sur l'utilisation de la mise en œuvre de la classe de base "défaut". :
class foo {
public:
virtual int interface();
};
int foo::interface()
{
printf( "default foo::interface() called\n");
return 0;
};
class pure_foo {
public:
virtual int interface() = 0;
};
int pure_foo::interface()
{
printf( "default pure_foo::interface() called\n");
return 42;
}
//------------------------------------
class foobar : public foo {
// no need to override to get default behavior
};
class foobar2 : public pure_foo {
public:
// need to be explicit about the override, even to get default behavior
virtual int interface();
};
int foobar2::interface()
{
// foobar is lazy; it'll just use pure_foo's default
return pure_foo::interface();
}
Je ne suis pas sûr qu'il y ait beaucoup de prestations - peut-être dans les cas où une conception a commencé avec une classe abstraite, alors au fil du temps constaté que beaucoup de classes de béton dérivées mettaient en œuvre le même comportement, ils ont donc décidé de déplacer ce comportement. dans une mise en œuvre de la classe de base pour la fonction virtuelle pure.
Je suppose qu'il pourrait également être raisonnable de mettre un comportement commun dans la mise en œuvre de la classe de base de la fonction virtuelle pure que les classes dérivées devraient être censées modifier/améliorer/augmenter.
The Almight Herb Sutter, ancien président du comité standard C++, a donné 3 scénarios où vous pourriez envisager de fournir des implémentations pour des méthodes virtuelles pures.
Je dois dire que personnellement, je ne trouve aucun d'entre eux convaincant et considérons généralement que cela était l'une des verrues sémantiques de C++. Il semble que C++ sort de sa façon de construire et de déchirer des vtables abstrait-parents, que les expose brièvement seulement pendant la construction/destruction des enfants, et ensuite Les experts de la communauté recommandent à l'unanimité Ne jamais les utiliser .
Un cas d'utilisation appelle la fonction virtuelle pure du constructeur ou du destructeur de la classe.
La seule différence de fonction virtuelle avec le corps et la fonction virtuelle pure avec le corps est que l'existence d'une seconde instanciation prévention. Vous ne pouvez pas marquer la classe Résumé en C++.
Cette question peut vraiment être déroutante lors de l'apprentissage de l'OOD et C++. Personnellement, une chose qui vient constamment dans ma tête était quelque chose comme: Si j'avais besoin d'une fonction virtuelle pure pour avoir également une mise en œuvre, alors pourquoi la rendre "pure" en premier lieu? Pourquoi ne pas juste laisser cela seulement "virtuel" et avoir tiré à la fois avantages et remplacer la mise en œuvre de la base?
La confusion vient au fait que de nombreux développeurs considèrent l'absence de carrosserie/mise en œuvre comme objectif principal/avantage de définir une fonction virtuelle pure. Ce n'est pas vrai! L'absence de corps est dans la plupart des cas une conséquence logique d'avoir une fonction virtuelle pure. Le principal avantage d'avoir une fonction virtuelle pure est la définition d'un contrat! En définissant une fonction virtuelle pure, vous souhaitez forcer chaque dérivé pour toujours fournir sa propre mise en œuvre de la fonction. Cet "aspect contractuel" est très important surtout si vous développez quelque chose comme une API publique. Faire la fonction que Virtual n'est pas si suffisante car les dérivés ne sont plus obligés de fournir leur propre mise en œuvre. Par conséquent, vous risquez de perdre l'aspect du contrat (cela peut être limitant dans le cas d'une API publique). Comme indiqué généralement: "Les fonctions virtuelles peuvent être annulées, les fonctions virtuelles pures doivent être annulées." Et dans la plupart des cas, les contrats sont des concepts abstraits afin qu'il n'a pas de sens que les fonctions virtuelles pures correspondantes ont une implémentation.
Mais parfois, et parce que la vie est bizarre, vous voudrez peut-être établir un fort contrat entre les dérivés et leur souhait également de bénéficier d'une implémentation par défaut tout en précisant leur propre comportement au contrat. Même si la plupart des auteurs du livre recommandent d'éviter de vous occuper de ces situations, la langue nécessaire pour fournir un filet de sécurité pour empêcher le pire! Une fonction virtuelle simple ne serait pas suffisante car il pourrait y avoir un risque d'échapper au contrat. La solution C++ fournie était donc pour permettre aux fonctions virtuelles pures de pouvoir également fournir une implémentation par défaut.
L'article Sutter cité ci-dessus donne des cas d'utilisation intéressante d'avoir des fonctions virtuelles pures avec le corps.