2013-08-28 9 views
21

Ho difficoltà a trovare i risultati su google per questo.non nomina un membro di dati non statici o una classe di base

struct a { 
    float m_x; 
    float m_z; 
public: 
    a(float x): m_x(x) {} 
}; 

class b : public a { 
    b(float z): m_z(z) {} 
}; 

Su clang 3.2:

error: member initializer 'm_z' does not name a non-static data member or base class 
    b(float z): m_z(z) {} 
+0

Perché? Non ho ancora creato un "diamante dell'eredità malvagia". @AndreyT la risposta accettata in quella domanda dice di fare un base ctor. Ne ho uno ... oh. Credo di aver bisogno di chiamare il censore della classe base, non il membro ctor. ok. –

+0

@WhozCraig: anche se è una base virtuale, non ti consente di inizializzare i membri * indiretti *. L'ereditarietà virtuale potrebbe richiedere l'inizializzazione di * basi * indirette, ma non membri. – AnT

+1

@Steven Lu: la risposta accettata dice che 'a :: m_z' può essere inizializzato solo dall'elenco di inizializzazione del costruttore di' a'. Non può essere menzionato nella lista di inizializzazione del costruttore di 'b' (come nel tuo codice).La lingua non lo consente. Questo è il punto. Cioè devi aggiungere un altro parametro al costruttore di 'a' specificatamente per' m_z' (come hai fatto per 'm_x') e passare il valore iniziale da' b' a quel costruttore. A proposito, nel tuo codice qui sopra devi fare riferimento al costruttore di 'a' dal costruttore di' b'. Altrimenti, non verrà compilato, poiché non hai un costruttore predefinito in 'a'. – AnT

risposta

26

No, non è possibile inizializzare i membri della classe base dalla lista di inizializzazione direttamente. Questo è perché l'ordine di inizializzazione procede in questo modo

C++ standard n3337 § 12.6.2/10

In un costruttore non delega, procede inizializzazione del seguente ordine:

- Innanzitutto, e solo per il costruttore della classe derivata più (1.8), le classi di base virtuali vengono inizializzate nell'ordine e vengono visualizzate in una traversata da sinistra a destra in profondità del grafico diretto di base c lasses, dove "left-to-right" è l'ordine di aspetto delle classi base nella classe derivata -specificatore-base-elenco.

- Poi, classi base dirette vengono inizializzati in ordine di dichiarazione come appaiono nella base-specificatore-list (indipendentemente dall'ordine delle mem-inizializzatori).

- Poi, non statici membri di dati sono inizializzati nell'ordine in cui sono stati dichiarati nella definizione della classe (ancora una volta indipendentemente dall'ordine dei MEM-inizializzatori).

- Infine, la dichiarazione composta del corpo del costruttore viene eseguita.

[Nota: l'ordine di dichiarazione è obbligatorio per garantire che gli oggetti secondari di base e membri vengano distrutti nell'ordine inverso di inizializzazione . - nota end]

Quindi è possibile specificare un costruttore in una classe di base (che può essere protetta) e l'uso che uno nella lista di inizializzazione di classe derivata (should be preferred) o si può assegnare a un membro della classe di base nel corpo del ctor di classe derivata (comportamento diverso, effetto diverso e anche meno efficiente - si assegna al membro predefinito inizializzato (già ha un valore)).

Nel primo caso si potrebbe scrivere in questo modo:

struct A { 
    float m_x; 
    float m_z; 
    A(){} 
protected: 
    A(float x): m_x(x) {} 
}; 

class B : public A { 
public: 
    B(float z) : A(z) {} 
    // alternatively 
    // B(float z) { 
    //  m_x = z; 
    // } 
}; 

int main(){ 
    B b(1); 
    return 0; 
} 
Problemi correlati