Perché una funzione virtuale pura è inizializzata da 0?


147

Dichiariamo sempre una funzione virtuale pura come:

virtual void fun () = 0 ;

Cioè, è sempre assegnato a 0.

Quello che capisco è che questo è per inizializzare la voce vtable per questa funzione su NULL e qualsiasi altro valore qui provoca un errore di tempo di compilazione. Questa comprensione è corretta o no?


12
Nota che vtable non è un requisito linguistico, ma solo un'opzione di implementazione per i metodi virtuali. Un compilatore potrebbe creare la stessa astrazione con un'implementazione diversa (ovvero, senza vtable e senza alcun elemento che contiene 0)
David Rodríguez - dribeas,

@hype Re la tua domanda supplementare - questo è quello che dice la mia risposta (e molti altri).

Solo curioso, cosa succede se do, virtual void func() = 100;
krithikaGopalakrisnan il

Risposte:


161

Il motivo =0è che Bjarne Stroustrup non pensava di poter ottenere un'altra parola chiave, come "pura" oltre la comunità C ++ al momento dell'implementazione della funzione. Questo è descritto nel suo libro, The Design & Evolution of C ++ , sezione 13.2.3:

La sintassi curiosa = 0 è stata scelta ... perché al momento non vedevo alcuna possibilità di ottenere una nuova parola chiave accettata.

Dichiara inoltre esplicitamente che questo non deve impostare la voce vtable su NULL e che farlo non è il modo migliore per implementare le funzioni virtuali pure.


4
Sì, è solo sintassi. Ho visto molti progetti che #define PURE = 0 e diranno il vuoto virtuale Foo () PURE;
i_am_jorf,

79
Si prega di Dio mi tenere lontano da quei progetti :-)

27
È molto meno peggio di #define BEGIN {#define END} ;-) e l'ho visto a volte.
Toon Krijthe

5
Questo genere di cose eleganti mi fa pensare che il C ++ non sia molto raffinato. È strano considerando che è così usato. Spero che la lingua sia migliore con il passare dei giorni.
jokoon

19
Quindi, in altre parole, Bjarne era "di fronte a una scadenza" e "ha usato un trucco" per superare un "difetto di progettazione";) (Solo essere faceto)
Carl

78

Come per la maggior parte delle domande "Perché" sul design del C ++, il primo posto da guardare è The Design and Evolution of C ++ , di Bjarne Stroustrup 1 :

La curiosa =0sintassi è stata scelta rispetto all'ovvia alternativa dell'introduzione di una nuova parola chiave pureo abstractperché al momento non vedevo alcuna possibilità di ottenere una nuova parola chiave accettata. Se avessi suggerito pure, la versione 2.0 sarebbe stata spedita senza classi astratte. Con una scelta tra una sintassi migliore e le classi astratte, ho scelto le classi astratte. Piuttosto che rischiare il ritardo e incorrere in certi scontri pure, ho usato la tradizionale convenzione C e C ++ di usare 0 per rappresentare "non lì". La =0sintassi si adatta alla mia opinione che un corpo di funzione sia l'inizializzatore di una funzione anche con la vista (semplicistica, ma di solito adeguata) dell'insieme di funzioni virtuali implementata come vettore di puntatori di funzione. [...]

1 §13.2.3 Sintassi


29

La sezione 9.2 dello standard C ++ fornisce la sintassi per i membri della classe. Include questa produzione:

pure-specifier:
    = 0

Non c'è niente di speciale nel valore. "= 0" è solo la sintassi per dire "questa funzione è pura virtuale". Non ha nulla a che fare con l'inizializzazione, i puntatori null o il valore numerico zero, sebbene la somiglianza con queste cose possa avere un valore mnemonico.


5
+1 per fare riferimento allo standard C ++. È sorprendente che una delle migliori risposte possibili abbia ottenuto solo 1 voto finora. Leggere lo standard dovrebbe essere il primo passo per risolvere le domande C ++.
mloskot,

7
@mloskot: forse perché non risponde alla domanda del PO, riafferma la situazione?
solo qualcuno

6
@just somebody - Include la citazione standard che afferma qual è la sintassi della dichiarazione di funzione virtuale pura e che la sintassi usa pure-specifier = 0Cos'altro vorresti sapere? Sarebbe lo stesso che chiedere perché il corpo della funzione sia racchiuso in {} La risposta sarebbe, perché questo è ciò che definisce la sintassi C ++.
mloskot,

19

Non sono sicuro che ci sia qualche significato dietro questo. È solo la sintassi della lingua.


16

Il C ++ ha sempre evitato di introdurre nuove parole chiave, poiché le nuove parole riservate rompono i vecchi programmi che usano queste parole per identificatori. È spesso visto come uno dei punti di forza del linguaggio che rispetta il vecchio codice per quanto possibile.

La = 0sintassi potrebbe effettivamente essere stata scelta in quanto assomiglia all'impostazione di una voce vtable 0, ma questo è puramente simbolico. (La maggior parte dei compilatori assegna tali voci vtable a uno stub che emette un errore prima di interrompere il programma.) La sintassi è stata principalmente scelta perché non era stata utilizzata per nulla prima e ha salvato introducendo una nuova parola chiave.


3
+1 per spiegare lo svantaggio di introdurre una nuova parola chiave. È utile per capire la logica, ma la sintassi del C ++ mi sembra assurdamente contorta per me e vorrei che l'avrebbero resa più leggibile dall'uomo - una pureparola chiave sarebbe stata grandiosa nel mio libro. Ad ogni modo, è bene capire la logica.
Keith Pinson,

@KeithPinson Se vuoi una parola chiave pura, puoi farlo #define pure = 0.
jdh8,

@ jdh8: Ugh. Solo ... Ugh.
sabato

Come nota a margine, in una classe con Bjarne ha detto che voleva davvero inserire la parola chiave "pura" in C ++ ... ma ha cercato di ottenerla molto tardi nel ciclo prima che il compilatore C ++ fosse spedito (IIRC meno di due settimane). Apparentemente, non ce l'ha fatta.
ThePhD

@ThePhD: ISTR lo dice anche da qualche parte in D&E. (Sono troppo pigro per cercarlo, però.)
sbi

11

Il C ++ deve avere un modo per distinguere una funzione virtuale pura da una dichiarazione di una normale funzione virtuale. Hanno scelto di usare la = 0sintassi. Avrebbero potuto facilmente fare lo stesso aggiungendo una parola chiave pura. Ma C ++ è piuttosto detestabile aggiungere nuove parole chiave e preferisce usare altri meccanismi per introdurre funzionalità.


2
-0: quando non hai nulla di sostanziale da dire da solo, usa una citazione estesa (vedi la risposta di Jerry Coffin per +1;)
solo qualcuno

7

In questo caso, nulla è "inizializzato" o "assegnato" zero. = 0in solo un costrutto sintattico costituito da =e0 token, che non ha assolutamente alcuna relazione con l'inizializzazione o l'assegnazione.

Non ha alcuna relazione con alcun valore reale in "vtable". Il linguaggio C ++ non ha nozione di "vtable" o qualcosa del genere. Vari "vtables" non sono altro che dettagli di implementazioni specifiche.


3

Ricordo di aver letto che la giustificazione per la sintassi divertente era che era più facile (in termini di accettazione degli standard) che introdurre un'altra parola chiave che avrebbe fatto la stessa cosa.

Credo che questo sia stato menzionato in The Design and Evolution of C ++ di Bjarne Stroustrup.


2

Suppongo che questo sia solo una parte della grammatica C ++. Non credo che ci siano restrizioni su come i compilatori implementano effettivamente questo per un determinato formato binario specifico. Probabilmente hai pensato che fosse giusto per i primi compilatori C ++.


2

La = 0dichiara una funzione virtuale pura .

Ciò che è chiaro è che si tratta di inizializzare la voce vtable per questa funzione su NULL e qualsiasi altro valore qui genera un errore di tempo di compilazione

Non penso sia vero. È solo una sintassi speciale. La vtable è definita dall'implementazione. Nessuno afferma che una voce di vtable per un membro puro debba essere effettivamente azzerata al momento della costruzione (sebbene la maggior parte dei compilatori gestisca vtables in modo simile).


4
In realtà non è vero. Non c'è niente di sbagliato nel fornire una definizione per una pura funzione virtuale. L'unica cosa che = 0fa è rendere l'intera classe astratta e proibire le chiamate virtuali a funzioni pure. Le chiamate non virtuali sono ancora perfettamente perfette, ovvero quando viene utilizzata la definizione (se ne è stata fornita una).
Il

Guarda l'output Godbolt. Non c'è spazio per l'ambiguità o la speculazione. Daro 'uno sguardo più tardi
Lewis Kelsey

Sembra che sostituisca la voce con __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… anziché Base :: f ()
Lewis Kelsey,

1

Bene, puoi anche inizializzare la voce vtable per puntare a una funzione effettiva "

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

Sembra intuitivo che la voce vtable possa essere definita in modo che non punti da nessuna parte (0) o verso una funzione. Lasciandoti specificare il tuo valore perché probabilmente si tradurrebbe in immondizia anziché in una funzione. Questo è il motivo per cui "= 0" è consentito e "= 1" non lo è. Ho il sospetto che Neil Butterworth abbia ragione sul perché "= 0" è usato affatto


1
Anche io avevo un'opinione simile, ma poiché molti hanno citato gli standard e i commenti di Bjarne sullo stesso, abbiamo una minima possibilità di argomentazione :)
mukeshkumar
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.