2009-05-07 14 views

risposta

7

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.

+1

Quando almeno un metodo è virtuale in una classe, è necessario disporre di un distruttore virtuale. – stefanB

0

Le funzioni dell'interfaccia dovrebbero essere, in generale, virtuali. Le funzioni che forniscono funzionalità fisse non dovrebbero.

2

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.

0

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.

+0

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. –

+1

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. –

1

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.
1

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.

4

È 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.

4

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.

+0

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

Problemi correlati