2012-12-14 18 views

risposta

183

Questa è davvero l'idea. Il punto è che si è esplicito su quello che vuoi dire, in modo che un errore altrimenti silenziosa può essere diagnosticato:

struct Base 
{ 
    virtual int foo() const; 
}; 

struct Derived : Base 
{ 
    virtual int foo() // whoops! 
    { 
     // ... 
    } 
}; 

Il codice sopra compila, ma non è quello che si può avere significato (notare il mancante const). Se hai detto invece, virtual int foo() override, si otterrebbe un errore del compilatore che la tua funzione non sta in effetti sovrascrivendo nulla.

+51

+1: Anche se, sfortunatamente, è un po 'una falsa pista quando le persone suggeriscono che la nuova funzione "override" "risolve" questo; devi ricordarti di usarlo, proprio come dovresti aver ricordato di scrivere il 'const';) –

+0

Ho appena realizzato che le definizioni di classe' esplicite' non sono state convertite in C++ 11. Huh. – aschepler

+1

@aschepler E cosa farebbe una definizione di classe 'esplicita'? Non ne ho mai sentito parlare. –

23

Wikipedia citazione:

L'override identificatore speciale significa che il compilatore controllerà la classe di base (es) per vedere se c'è una funzione virtuale con questa firma esatta. E se non c'è, il compilatore salterà fuori.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

Edit (il tentativo di migliorare un po 'la risposta):

Dichiarare un metodo come "override" si intende che tale metodo è destinato a riscrivere un metodo (virtuale) sulla classe base. Il metodo di override deve avere la stessa firma (almeno per i parametri di input) come metodo che intende riscrivere.

Perché è necessario? Bene, i seguenti due casi di errore comuni sono impediti:

  1. un errore di digitazione un tipo nel nuovo metodo. Il compilatore, ignaro del fatto che intende scrivere un metodo precedente, lo aggiunge semplicemente alla classe come nuovo metodo. Il problema è che il vecchio metodo è ancora lì, il nuovo è aggiunto proprio come un sovraccarico. In questo caso, tutte le chiamate verso il vecchio metodo funzioneranno come prima, senza alcun cambiamento nel comportamento (che sarebbe stato lo scopo della riscrittura).

  2. uno si dimentica di dichiarare il metodo nella superclasse come "virtuale", ma tenta comunque di riscriverlo in una sottoclasse. Sebbene questo sia apparentemente accettato, il comportamento non sarà esattamente come previsto: il metodo non è virtuale, quindi l'accesso attraverso i puntatori verso la superclasse terminerà chiamando il vecchio metodo (superclasse ') invece del nuovo metodo (sottoclasse').

Aggiunta di "override" disambigua chiaramente questo: attraverso questa, si sta dicendo al compilatore che tre cose si aspettano:

  1. c'è un metodo con lo stesso nome della superclasse
  2. questo il metodo nella superclasse è dichiarato come "virtuale" (che significa, riscritto)
  3. il metodo nella superclasse ha la stessa firma (input *) del metodo nella sottoclasse (il metodo di riscrittura)

Se uno di questi è falso, viene segnalato un errore.

* nota: il parametro di uscita è talvolta di tipo diverso ma correlato. Leggi le trasformazioni covarianti e controvarianti se interessati.

18

Trovato "override" è utile quando qualcuno ha aggiornato la firma del metodo virtuale della classe di base come l'aggiunta di un parametro facoltativo ma ha dimenticato di aggiornare la firma del metodo di classe derivata. In quel caso i metodi tra la base e la classe derivata non sono più relazione polimorfica. Senza la dichiarazione di override, è difficile scoprire questo tipo di bug.

+0

+1. Anche se l'override è un ottimo modo per scoprire questi problemi, anche una buona copertura dei test unitari dovrebbe essere d'aiuto. –

+0

Questo è esattamente il motivo per cui sono così entusiasta di questo nuovo specificatore. L'unico problema è che questa funzione deve essere già applicata per evitare errori causati da modifiche nelle classi base. ;-) – Wolf

Problemi correlati