Pourquoi une fonction virtuelle pure est-elle initialisée par 0?

147

Nous déclarons toujours une fonction virtuelle pure comme:

virtual void fun () = 0 ;

C'est-à-dire qu'il est toujours attribué à 0.

Ce que je comprends, c'est qu'il s'agit d'initialiser l'entrée vtable pour cette fonction à NULL et que toute autre valeur ici entraîne une erreur de compilation. Cette compréhension est-elle correcte ou non?

mukeshkumar
la source
12
Notez que vtable n'est pas une exigence linguistique, mais simplement une option d'implémentation pour les méthodes virtuelles. Un compilateur pourrait créer la même abstraction avec une implémentation différente (c'est-à-dire sans vtable, et sans qu'aucun élément n'y soit 0)
David Rodríguez - dribeas
@hype Re votre question supplémentaire - c'est ce que dit ma réponse (et plusieurs autres).
Juste curieux, que se passe-t-il si je donne, virtual void func() = 100;
krithikaGopalakrisnan

Réponses:

161

La raison en =0est que Bjarne Stroustrup ne pensait pas pouvoir obtenir un autre mot-clé, tel que "pur", au-delà de la communauté C ++ au moment où la fonctionnalité était implémentée. Ceci est décrit dans son livre, The Design & Evolution of C ++ , section 13.2.3:

La syntaxe curieuse = 0 a été choisie ... car à l'époque je ne voyais aucune chance d'obtenir un nouveau mot-clé accepté.

Il déclare également explicitement que cela n'a pas besoin de définir l'entrée vtable sur NULL, et que cela n'est pas la meilleure façon d'implémenter des fonctions virtuelles pures.


la source
4
Oui, c'est juste de la syntaxe. J'ai vu beaucoup de projets qui #define PURE = 0 et ils diront virtual void Foo () PURE;
i_am_jorf
79
S'il vous plaît Dieu me garde loin de ces projets :-)
27
C'est beaucoup moins pire que #define BEGIN {#define END} ;-) et j'ai vu ça parfois.
Toon Krijthe
5
Ce genre de chose astucieuse me fait penser que C ++ n'est pas très poli. C'est bizarre vu qu'il est tellement utilisé. J'espère que la langue sera meilleure avec les jours qui passent.
jokoon
19
Donc, en d'autres termes, Bjarne a été "confronté à une date limite" et "a utilisé un hack" pour surmonter un "défaut de conception";) (Juste être facétieux)
Carl
78

Comme pour la plupart des questions «Pourquoi» sur la conception de C ++, le premier endroit à regarder est La conception et l'évolution du C ++ , par Bjarne Stroustrup 1 :

La curieuse =0syntaxe a été choisie plutôt que l'alternative évidente d'introduire un nouveau mot pure- clé ou abstractparce qu'à l'époque je ne voyais aucune chance d'obtenir un nouveau mot-clé accepté. Si j'avais suggéré pure, la version 2.0 aurait été livrée sans classes abstraites. Étant donné le choix entre une syntaxe plus agréable et des classes abstraites, j'ai choisi des classes abstraites. Plutôt que de risquer des retards et d'encourir certains combats pure, j'ai utilisé la convention traditionnelle C et C ++ d'utiliser 0 pour représenter «pas là». La =0syntaxe correspond à mon point de vue selon lequel un corps de fonction est l'initialiseur d'une fonction également avec la vue (simpliste, mais généralement adéquate) de l'ensemble des fonctions virtuelles implémentées en tant que vecteur de pointeurs de fonction. [...]

1 §13.2.3 Syntaxe

Jerry Coffin
la source
29

La section 9.2 du standard C ++ donne la syntaxe des membres de classe. Il comprend cette production:

pure-specifier:
    = 0

Il n'y a rien de spécial dans la valeur. "= 0" est juste la syntaxe pour dire "cette fonction est purement virtuelle". Cela n'a rien à voir avec l'initialisation ou les pointeurs nuls ou la valeur numérique zéro, bien que la similitude avec ces choses puisse avoir une valeur mnémonique.

Kristopher Johnson
la source
5
+1 pour faire référence à la norme C ++. C'est une sorte de surprise que l'une des meilleures réponses possibles et n'obtienne qu'un vote jusqu'à présent. La lecture de la norme doit être la toute première étape pour résoudre les questions C ++.
mloskot
7
@mloskot: peut-être parce qu'il ne répond pas à la question du PO, ne fait que reformuler la situation?
juste quelqu'un
6
@just somebody - Il inclut la citation standard qui indique quelle est la syntaxe de la déclaration de fonction virtuelle pure et que la syntaxe utilise pure-specifier. = 0Que voulez-vous savoir d'autre? Ce serait la même chose que de demander pourquoi le corps de la fonction est enveloppé avec {} La réponse serait, parce que c'est ce que définit la syntaxe C ++.
mloskot
19

Je ne sais pas s'il y a un sens derrière cela. C'est juste la syntaxe du langage.

cquillen
la source
16

C ++ a toujours évité d'introduire de nouveaux mots-clés, car les nouveaux mots réservés cassent les anciens programmes qui utilisent ces mots pour les identificateurs. Il est souvent considéré comme l'une des forces du langage de respecter le plus possible l'ancien code.

La = 0syntaxe peut en effet avoir été choisie car elle ressemble à la définition d'une entrée de vtable 0, mais c'est purement symbolique. (La plupart des compilateurs attribuent de telles entrées de vtable à un stub qui émet une erreur avant d'abandonner le programme.) La syntaxe a été principalement choisie car elle n'était utilisée pour rien avant et cela a sauvé l'introduction d'un nouveau mot-clé.

sbi
la source
3
+1 pour expliquer l'inconvénient d'introduire un nouveau mot-clé. C'est utile pour comprendre le raisonnement, mais la syntaxe C ++ me semble absurdement alambiquée et j'aurais aimé qu'elle l'ait rendue plus lisible par l'homme - un puremot-clé aurait été génial dans mon livre. Quoi qu'il en soit, il est bon de comprendre la justification.
Keith Pinson
@KeithPinson Si vous voulez un mot clé pur, vous pouvez #define pure = 0.
jdh8
@ jdh8: Ugh. Juste ... Ugh.
sbi
En passant, dans une classe avec Bjarne, il a dit qu'il voulait vraiment obtenir le mot-clé "pur" en C ++ ... mais il a essayé de le faire entrer très tard dans le cycle avant que le compilateur C ++ ne soit expédié (IIRC moins de deux semaines). Apparemment, il n'est pas arrivé.
ThePhD
@ThePhD: ISTR, il dit aussi cela quelque part dans D&E. (Je suis trop paresseux pour le rechercher, cependant.)
sbi
11

C ++ doit avoir un moyen de distinguer une fonction virtuelle pure d'une déclaration d'une fonction virtuelle normale. Ils ont choisi d'utiliser la = 0syntaxe. Ils auraient pu facilement faire de même en ajoutant un mot clé pur. Mais C ++ répugne assez à ajouter de nouveaux mots clés et préfère utiliser d'autres mécanismes pour introduire des fonctionnalités.

JaredPar
la source
2
-0: lorsque vous n'avez rien de substantiel à dire par vous-même, utilisez une citation détaillée (voir la réponse de Jerry Coffin pour +1;)
juste quelqu'un
7

Rien n'est «initialisé» ou «attribué» zéro dans ce cas. = 0dans juste une construction syntaxique composée de =et de 0jetons, qui n'a absolument aucun rapport avec l'initialisation ou l'affectation.

Il n'a aucun rapport avec une valeur réelle dans "vtable". Le langage C ++ n'a aucune notion de "vtable" ou quoi que ce soit de ce genre. Diverses «vtables» ne sont rien de plus que des détails d'implémentations spécifiques.

Fourmi
la source
3

Je me souviens avoir lu que la justification de la syntaxe amusante était que c'était plus facile (en termes d'acceptation des normes) que d'introduire un autre mot-clé qui ferait la même chose.

Je crois que cela a été mentionné dans The Design and Evolution of C ++ par Bjarne Stroustrup.

Luke
la source
2

Je suppose que ce n'est qu'une partie de la grammaire C ++. Je ne pense pas qu'il y ait de restrictions sur la façon dont les compilateurs implémentent réellement cela pour un format binaire spécifique donné. Vous supposez probablement que c'était juste pour les premiers compilateurs C ++.

rui
la source
2

Le = 0déclare une fonction virtuelle pure .

Ce qui est compris, c'est qu'il s'agit d'initialiser l'entrée vtable pour cette fonction sur NULL et que toute autre valeur ici entraîne une erreur de compilation

Je ne pense pas que ce soit vrai. C'est juste une syntaxe spéciale. La vtable est définie par l'implémentation. Personne ne dit qu'une entrée vtable pour un membre pur doit être remise à zéro lors de la construction (bien que la plupart des compilateurs gèrent les vtables de la même manière).

Alexander Gessler
la source
4
Ce n'est en fait pas vrai. Il n'y a rien de mal à fournir une définition d'une fonction virtuelle pure. La seule chose à = 0faire est de rendre la classe entière abstraite et d'interdire les appels virtuels à des fonctions pures. Les appels non virtuels sont toujours parfaitement OK, c'est-à-dire lorsque la définition (si vous en avez fourni une) est utilisée.
Du
Regardez simplement la sortie godbolt. Il n'y a pas de place pour l'ambiguïté ou la spéculation. Je jetterai un coup d'œil moi-même plus tard
Lewis Kelsey
Il semble qu'il remplace l'entrée par __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/... au lieu de Base :: f ()
Lewis Kelsey
1

Eh bien, vous pouvez également initialiser l'entrée vtable pour pointer vers une fonction réelle "

 virtual void fun()
 {
     //dostuff()
 }

Il semble intuitif que l'entrée vtable puisse être définie pour ne pointer nulle part (0) ou vers une fonction. Le fait de vous laisser spécifier votre propre valeur pour cela entraînerait probablement un pointage vers des déchets plutôt que vers une fonction. Mais c'est pourquoi "= 0" est autorisé et "= 1" ne l'est pas. Je soupçonne que Neil Butterworth a raison sur la raison pour laquelle "= 0" est utilisé

Brian
la source
1
Même si j'avais une opinion similaire, mais comme beaucoup ont cité des normes et les commentaires de Bjarne à ce sujet, nous avons peu de chances de nous
disputer