Quando dichiaro una classe base, dovrei dichiarare tutte le funzioni in esso come virtuali, o dovrei avere un set di funzioni virtuali e un set di funzioni non virtuali che sono sicuro che non saranno ereditate?Devo dichiarare tutte le funzioni virtuali in una classe base?
risposta
Una funzione deve essere solo virtuale se una classe derivata implementerà quella funzione in un modo diverso.
Ad esempio:
class Base {
public:
void setI (int i) // No need for it to be virtual
{
m_i = i;
}
virtual ~Base() {} // Almost always a good idea
virtual bool isDerived1() // Is overridden - so make it virtual
{
return false;
}
private:
int m_i;
};
class Derived1 : public Base {
public:
virtual ~Derived() {}
virtual bool isDerived1() // Is overridden - so make it virtual
{
return true;
}
};
Di conseguenza, vorrei errore il lato di non avere nulla di virtuale se non si sa in anticipo che si intende sostituire o fino a quando si scopre che è necessario il comportamento. L'unica eccezione a questo è il distruttore, per il quale il suo è quasi il sempre che si desidera che sia virtuale in una classe base.
Le funzioni dell'interfaccia dovrebbero essere, in generale, virtuali. Le funzioni che forniscono funzionalità fisse non dovrebbero.
Io tendo a rendere solo le cose che voglio essere virtuale sovrascrivibile. Se le mie ipotesi iniziali su ciò che voglio escludere si rivelano errate, torno indietro e cambio la classe base.
Oh, e ovviamente rende sempre virtuale il tuo distruttore se stai lavorando su qualcosa da cui erediteresti.
Perché dichiarare qualcosa di virtuale finché non lo si sovrascrive davvero? Credo che non sia una questione di sicurezza o meno. Segui i fatti: è cancellato da qualche parte? No? Quindi non deve essere virtuale.
Questo si traduce in una situazione in cui se si desidera modificare una sottoclasse (per sovrascrivere un metodo precedentemente non sovrascritto), è necessario modificare la classe base (per rendere virtuale il metodo), il che significa che è necessario ricompilare tutto il codice che fa riferimento la classe base. In alcuni progetti la fragilità della classe base non è un problema, ma in altri lo è. Dipende dal tuo processo di compilazione e dal fatto che tu abbia pubblicato l'interfaccia della classe base. –
Quindi i metodi IMO dovrebbero essere virtuali se le sottoclassi sono autorizzate a sovrascriverli (e il polimorfismo di runtime è supportato), non se lo fanno effettivamente. –
Se si sta creando una classe base (si è sicuri che qualcuno deriva la classe) allora si può fare seguenti cose:
- Marchio distruttore virtuale (un must per classe base)
- definire i metodi che dovrebbe essere derivato da e renderlo virtuale.
- Definire metodi che non devono essere (o non devono essere derivati come non virtuali.
- Se le funzioni sono solo per classe derivata e non per classe di base, contrassegnare come come protetti.
Il compilatore non saprebbe quale parte effettiva del codice verrà eseguita quando il puntatore del tipo di base chiama una funzione virtuale. quindi l'effettivo pezzo di codice che deve essere eseguito deve essere valutato in fase di esecuzione in base a quale oggetto è puntato dal puntatore della classe base. Quindi evita l'uso della funzione virtuale se la funzione non è sovrascritta in una classe ereditata.
Versione TLDR: "è necessario disporre di un set di funzioni virtuali e un set di funzioni non virtuali che non si è certi che verranno ereditate." Perché le funzioni virtuali provocano una riduzione delle prestazioni in fase di esecuzione.
È necessario eseguire solo le funzioni che si intendono e il progetto per essere sovrascritti virtuali. Fare un metodo virtuale non è libero in termini di manutenzione e prestazioni (la manutenzione è il problema più grande IMHO).
Una volta che un metodo è virtuale diventa più difficile ragionare su qualsiasi codice che utilizza questo metodo.Perché invece di considerare quale sarebbe una chiamata al metodo, è necessario considerare cosa farebbero le chiamate al metodo N in quello scenario. N rappresenta il numero di sottoclassi che sovrascrivono quel metodo.
L'unica eccezione a questa regola è i distruttori. Dovrebbero essere virtuali in qualsiasi classe da cui si intende derivare. È l'unico modo per garantire che venga chiamato il distruttore appropriato durante la deallocazione.
L'idioma di interfaccia non virtuale (C++ Coding Standards articolo 39) dice che una classe base deve avere metodi di interfaccia non virtuali, consentendo alla classe base di garantire invarianti e metodi virtuali non pubblici per la personalizzazione della classe base comportamento da classi derivate. I metodi di interfaccia non virtuale chiamano i metodi virtuali per fornire il comportamento overridable.
Considera di aggiungere la fonte qui. Ho scoperto che si fa riferimento a "Standard di codifica C++, 101 regole, linee guida e best practice, Herb Sutter e Andrej Alexandrescu". Tuttavia, non esiste uno standard di codifica ufficiale in C++. – patrik
- 1. C++: funzioni virtuali private vs. funzioni virtuali puri
- 2. Ereditarietà delle funzioni virtuali
- 3. Devo dichiarare logger log4net una volta per classe o in classe base?
- 4. Chiamare funzioni virtuali tramite un riferimento alla classe base
- 5. Classe astratta C++ senza pure funzioni virtuali?
- 6. Perché utilizzare le funzioni virtuali?
- 7. funzioni virtuali oggetto affettare
- 8. Devo implementare IDisposable su tutte le classi o è sufficiente una classe base?
- 9. Perché le funzioni virtuali in C++ sono chiamate "virtuali"?
- 10. Sovrascrivere in modo sicuro le funzioni virtuali C++
- 11. Quando devo dichiarare session_start() ;?
- 12. Funzioni virtuali utilizzando oggetti di base e derivati
- 13. Perché dichiarare sempre le funzioni in JavaScript?
- 14. Implementazione corretta di funzioni virtuali in PHP?
- 15. Doxygen C++ - Non documentare le funzioni virtuali in una classe template
- 16. Domanda di polimorfismo/ereditarietà C++: ridefinizione delle funzioni di base vs funzioni virtuali
- 17. metodi virtuali Quando si esegue il un'istanza di una classe
- 18. Come impostare l'allineamento per le funzioni virtuali?
- 19. Perché devo ri-dichiarare le funzioni sottoposte a override nelle classi derivate in C++?
- 20. Carica tutte le funzioni in PowerShell da una determinata directory
- 21. Devo sigillare tutte le classi che non dovrei mai usare come classe base?
- 22. Le funzioni virtuali possono essere constexpr?
- 23. Principio delle funzioni virtuali in C++
- 24. Quando dovrei dichiarare le variabili in una classe PHP?
- 25. Richiesta di funzioni virtuali sovrascritte per chiamare le implementazioni di base
- 26. Dovrei considerare che dichiarare tutte le funzioni statiche C è una buona pratica?
- 27. override di funzioni non virtuali
- 28. Devo dichiarare le variabili iniettate come transitori in Java EE?
- 29. Perché dobbiamo dichiarare metodi virtuali come tali
- 30. Dove devo dichiarare le variabili statiche?
Quando almeno un metodo è virtuale in una classe, è necessario disporre di un distruttore virtuale. – stefanB