Come è stato detto da più persone che rispondono, non è possibile ritardare l'invocazione di un costruttore di classe base, ma Konrad has given a good answer che potrebbe risolvere il problema. Tuttavia, questo ha i suoi svantaggi (ad esempio, quando è necessario inizializzare diverse funzioni con valori i cui calcoli condividono i risultati intermedi), quindi, per essere completo, ecco un altro modo di risolvere il problema dell'ordine di inizializzazione fisso, per usando .
Dato l'ordine di inizializzazione fisso, se si ha il controllo sulla classe derivata (e in quale altro modo si farebbe a giocherellare con uno dei suoi operatori?), È possibile intrufolarsi in una base privata in modo che sta per essere inizializzato prima che l'altra base, che possono poi essere inizializzato con i valori già calcolati della base privato:
class my_dirty_little_secret {
// friend class the_class;
public:
my_dirty_little_secret(const std::string& str)
{
// however that calculates x, y, and z from str I wouldn't know
}
int x;
std::string y;
float z;
};
class the_class : private my_dirty_little_secret // must be first, see ctor
, public the_other_base_class {
public:
the_class(const std::string str)
: my_dirty_little_secret(str)
, the_other_base_class(x, y, z)
{
}
// ...
};
La classe my_dirty_little_secret
è una base privata in modo che gli utenti di the_class
non possono utilizzarlo, tutti i suoi contenuti sono privati, con un'amicizia esplicita che concede solo l'accesso allo the_class
. Tuttavia, poiché è elencato per primo nell'elenco della classe base, verrà costruito in modo affidabile prima dello the_other_base_class
, quindi qualsiasi cosa calcoli può essere utilizzato per inizializzarlo.
Un bel commento all'elenco delle classi di base si spera che impedisca agli altri di rompere le cose tramite il refactoring.
Grazie, non ho pensato solo a chiamare una funzione, quindi funzionerà, ma sarà un po 'complicato perché il costruttore ha 2 parametri. Accetterò questa risposta quando posso (a meno che non ne esca uno migliore, ovviamente). A proposito, hai ragione a non essere in grado di farlo in Java e C#, ho pensato che fosse possibile in Java perché è stato fatto usando 'super (...)' sul corpo del metodo, ma ho notato che ora deve essere la prima linea – placeholder
+1 Dovresti rendere some_function() statico per documentare il fatto che non usa nessuna delle variabili di istanza della classe (che non sono state inizializzate). –
Interessante, mai visto prima. Presumo che la funzione chiamata possa essere una funzione di classe derivata. – PatrickV