2011-01-26 7 views
5

DOMANDA 1)costruttore C++ Base chiama con il parametro che saranno costruiti nel costruttore derivato

class Base { 
    Base(std::string name); 

    virtual std::string generateName(); 
} 

class Derived : Base { 
    Derived(); 

    virtual std::string generateName(); 
} 

Qui viene la domanda:

quale metodo verrà invitato generateName()?

Derived :: Derived : Base(generateName()) { 
    //what method will be called on generateName() ? 
} 

DOMANDA 2)

come dovrei farlo? se il costruttore predefinito deve accettare un parametro, ma ho bisogno di generare quel parametro nel costruttore Derivato?

risposta

8

In primo luogo, la soluzione: utilizzare una funzione membro statico o una funzione non membro.

Per quanto riguarda il comportamento, verrà chiamato Derived::generateName(). La lunga frase nella ++ standard C che definisce questo comportamento dice (C++ 03 12,7/3):

Quando una funzione virtuale viene chiamato direttamente o indirettamente da un costruttore (anche dal mem-inizializzatore di dati membro) o da un distruttore e l'oggetto a cui si applica la chiamata è l'oggetto in costruzione o distruzione, la funzione chiamata è quella definita nella classe del costruttore o della classe di distruttore o in una delle sue basi, ma non una funzione che esegue l'override in una classe derivata dalla classe del costruttore o del distruttore, o sovrascrivendola in una delle altre classi base dell'oggetto più derivato.

Poiché il costruttore in esecuzione al momento della chiamata virtuale è il costruttore Derived, Derived::generateName() è chiamato.

Una risposta eliminata fa giustamente riferimento a un articolo di Scott Meyers che consiglia "Never Call Virtual Functions during Construction or Destruction." Le regole per ciò che viene chiamato overrider sono complesse e difficili da ricordare.

+3

Questo sarebbe vero se 'generateName()' veniva chiamato da * inside * 'Base :: Base'. Ma qui, lo chiamiamo nella lista di inizializzazione, prima di entrare in 'Base :: Base'. È ancora vero? –

+0

Ah, hai aggiornato la tua risposta. Questo sembra adesso, quindi +1. –

+1

@Oli: No. Ho sbagliato e ho corretto la risposta dopo aver esaminato il problema e eseguito alcuni test. Sono in qualche modo sorpreso dal comportamento specificato. Mi sembra sbagliato ;-) (Si rompe il modello che generalmente ho usato per ragionare sulle chiamate alle funzioni virtuali durante la costruzione e ora devo tornare indietro e trovare tutte le risposte in cui ho descritto in modo errato il processo .. .) Grazie per aver chiesto la risposta originale. –

1

prendere due ...

ho fatto una corsa con le chiamate a generateName() nel initialiser classe base ed entrambi i costruttori. L'uscita mi ha lasciato perplesso:

Derived (called from Derived's Base initializer) 
Base (called from Base ctor) 
Derived (called from Derived ctor) 

avrei mai immaginato che una classe potrebbe trasformarsi da essere un derivato ad una base, poi di nuovo a un derivato in una singola sequenza di costruzione. Si impara qualcosa di nuovo ogni giorno.

Problemi correlati