Domanda

Ho appena notato questo in qualche codice:

class Foo {
[...]
private:
    virtual void Bar() = 0;
[...]
}

Questo ha qualche scopo?

(Sto cercando di trasferire del codice da VS a G++ e questo ha attirato la mia attenzione)

È stato utile?

Soluzione

questo Herb Sutter articolo sul motivo per cui ci si vuole fare un tale cosa.

Altri suggerimenti

Questa è una funzione virtuale pura che sembra essere privata.Ciò fa sì che una classe derivata debba implementare il metodo.In questo caso Bar.

Penso che potresti essere confuso perché questo viene fatto per creare "interfacce" in C++ e molte volte le persone le considerano pubbliche.Esistono casi in cui potresti voler definire un'interfaccia privata in cui un metodo pubblico utilizza tali metodi privati ​​per garantire l'ordine in cui vengono chiamati.(Credo che questo sia chiamato il metodo del modello)

Per un esempio relativamente brutto :)

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 consente esplicitamente:

§10.3 afferma nulla di accesso identificatore e contiene anche una nota in calce nella seconda clausola affermando nel contesto delle sostituzioni funzione virtuale:

  

[...] controllo di accesso (clausola 11) è   non considerati nella determinazione   prioritario.

Il codice è completamente legale.

La solita risposta "accademica" è:. Specificatori di accesso e virtualità sono ortogonali - uno non influisce l'altro

Un po 'di risposta più pratica: le funzioni virtuali private sono spesso utilizzati per implementare il Template Method modello di progettazione. In linguaggi che non supportano funzioni virtuali private, il metodo modello deve essere pubblico anche se non è veramente destinata a essere una parte dell'interfaccia.

Citerò una breve spiegazione del grande Domande frequenti su C++ Lite che lo riassume bene:

23.4] Quando qualcuno dovrebbe usare virtuali privati?

Quasi mai.

I virtuali protetti vanno bene, ma i virtuali privati ​​sono di solito una perdita netta.Motivo:I virtuali privati ​​confondono i nuovi programmatori C ++ e la confusione aumenta i costi, ritardi e degradano il rischio.

I nuovi programmatori di C ++ vengono confusi dai virtuali privati ​​perché pensano che un virtuale privato non possa essere ignorato.Dopotutto, una classe derivata non può accedere ai membri privati ​​nella sua classe di base, quindi come, lo chiedono, potrebbe scavalcare un virtuale privato dalla sua classe base?Ci sono spiegazioni per quanto sopra, ma questo è accademico.Il vero problema è che quasi tutti vengono confusi la prima volta che si imbattono in virtuali privati ​​e la confusione è cattiva.

A meno che non vi sia un motivo convincente contrario, evita virtuali privati.


Nel frattempo le FAQ Lite di C++ sono state aggiornate:

A proposito, confonde la maggior parte dei programmatori C++ alle prime armi il fatto che i virtuali privati ​​possano essere sovrascritti, per non parlare della loro validità.A tutti noi è stato insegnato che i membri privati ​​di una classe base non sono accessibili nelle classi da essa derivate, il che è corretto.Tuttavia questa inaccessibilità da parte della classe derivata non ha nulla a che fare con il meccanismo di chiamata virtuale, che riguarda la classe derivata.Poiché ciò potrebbe confondere i principianti, le domande frequenti su C++ consigliavano in precedenza di utilizzare virtuali protetti anziché virtuali privati.Tuttavia, l'approccio virtuale privato è ormai abbastanza comune da rendere meno preoccupante la confusione dei principianti.

Si tratta di una funzione virtuale pura. Qualsiasi implementazione finale che è derivato da "Food" DEVE attuare la funzione "Bar".

Si rende la pura funzione virtuale in contrasto virtuale.

No implementazione viene fornito di default e l'intento è che l'implementazione della funzione deve essere specificata da una classe che eredita. Questo può essere sovrascritto tuttavia.

A volte vedi classi complete in cui tutte le funzioni membro sono specificati come pure virtuale in questo modo.

Queste sono le classi base astratte, a volte indicato come classi di interfaccia, e il progettista della ABC è che ti dice: "Ora ho idea di come questa funzionalità sarebbe stata attuata per tutte le specializzazioni di questa classe di base. Ma, si deve avere tutti questi definito per la tua specializzazione per lavorare e si sa come l'oggetto deve comportarsi".

Modifica Spiacenti, appena individuato il fatto che la funzione virtual puro elemento è privato. (Grazie Michael) Questo cambia le cose un po '.

Quando questa classe base viene ereditata utilizzando l'ereditarietà privata cambia le cose. Fondamentalmente ciò che il progettista della classe di base sta facendo sta dicendo è che, quando la classe derivata chiama una funzione non-privato nella classe base. parte del comportamento è stata delegata alla tua specializzazione della funzione nella classe derivata. Il membro non privato sta facendo "qualcosa" e parte di quel "qualcosa" è una chiamata, tramite la funzione di classe di base virtuale pura, per l'implementazione.

Quindi, qualche funzione pubblica in Foo sta chiamando la funzione bar all'interno Foo, e si basa sul fatto che si fornire un'implementazione specializzata della funzione bar per il vostro caso particolare.

Scott Meyers si riferisce a questo come "implementato in termini di".

A proposito Proprio ridacchiando sul numero di risposte che sono stati rapidamente cancellati da persone che anche non ha visto il "stampa fine" in questione! (-:

HTH

applausi,

L'unico scopo sembra servire è quello di fornire un'interfaccia comune.

A proposito, anche se una funzione è dichiarata come privata virtuale, può ancora essere implementato e chiamato con l'istanza di classe o da amici.

Tuttavia, questo genere di cose di solito pensato per servire come interfaccia, ma non lo faccio in questo modo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top