2013-08-07 25 views
35

Qualcuno potrebbe spiegare dove i compilatori C++ mantengono i valori predefiniti per i parametri per le funzioni virtuali? So che non è una buona idea modificare questi parametri nelle classi figlie, ma perché? Grazie.Parametri predefiniti delle funzioni virtuali

+1

Avete qualche esempio di codice? –

risposta

51

È una cattiva idea perché non sono tenuti da nessuna parte.

I valori predefiniti utilizzati saranno quelli definiti nel tipo statico (in fase di compilazione). Quindi, se dovessi cambiare i parametri predefiniti in una sostituzione, ma hai chiamato la funzione tramite un puntatore o riferimento di classe base, verrebbero utilizzati i valori predefiniti nella base.

#include <iostream> 

struct Base 
{ 
    virtual ~Base(){ } 
    virtual void foo(int a=0) { std::cout << "base: " << a << std::endl; } 
}; 

struct Derived : public Base 
{ 
    virtual ~Derived() { } 
    virtual void foo(int a=1) { std::cout << "derived: " << a << std::endl; } 
}; 

int main() 
{ 
    Base* derived = new Derived(); 
    derived->foo(); // prints "derived: 0" 
    delete derived; 
} 
+9

Per capire come funziona, il valore predefinito è compilato nel sito di chiamata (dove è noto solo il tipo statico), quindi il compilatore traduce effettivamente 'derived-> foo()' in 'derived-> foo (0)' a compilare il tempo. –

5

Dare funzioni virtuali initializers argomento predefinito tende a sconfiggere il polimorfismo e introdurre inutili complessità in una gerarchia di classe.

considerare il seguente codice non conforme

class Thing { 
    public: 
    virtual ~Thing(); 
    virtual void doItNTimes(int numTimes = 10); 
    virtual void doItThisHigh(double howHigh = 1.0); 
    // ... 
}; 
class MyThing : public Thing { 
    public: 
    void doItNTimes(int numTimes); 
    void doItThisHigh(double howHigh = 2.2); 
    // ... 
}; 

Un inizializzatore di default non è parte del tipo di una firma di funzione e non partecipa a priorità assoluta o nascondersi. Pertanto, entrambe le funzioni virtuali della classe base mostrate in questo esempio di codice non conforme vengono sovrascritte nella classe derivata. Tuttavia, le differenze nello stato degli inizializzatori degli argomenti predefiniti nella classe base e nelle interfacce di classe derivate provocano differenze nel comportamento a seconda dell'interfaccia utilizzata per accedere a un oggetto.

MyThing *mt = new MyThing; 
Thing *t = mt; 
t->doItNTimes(); // default of 10 
mt->doItNTimes(); // compile time error! 
t->doItThisHigh(); // default of 1.0! 
mt->doItThisHigh(); // default of 2.2 

In questo pezzo di codice, l'intenzione del progettista della classe MyThing non è chiaro. Presumibilmente, è importante che il valore predefinito di doItThisHigh per un oggetto di tipo MyThing sia 2.2. Tuttavia, non è chiaro se tale valore debba essere utilizzato anche di default quando un MyThing viene manipolato attraverso la sua interfaccia Thing.

Per maggiori dettagli si rimanda al link qui sotto https://www.securecoding.cert.org/confluence/display/cplusplus/OOP04-CPP.+Prefer+not+to+give+virtual+functions+default+argument+initializers

Problemi correlati