2010-10-21 18 views
18

Ho una domanda sull'inizializzazione dei membri ereditati nel costruttore della classe derivata. Esempio di codice:C++: inizializzazione del campo ereditato

class A 
    { 
public: 
    int m_int; 
    }; 

class B: public A 
    { 
public: 
    B():m_int(0){} 
    }; 

Questo codice mi dà il seguente risultato:

In constructor 'B::B()': Line 10: error: class 'B' does not have any field named 'm_int'

(vedi http://codepad.org/tn1weFFP)

sto cercando di indovinare perché questo accade?deve essere membro di B e la classe padre A deve essere già inizializzata quando si verifica l'inizializzazione di m_int in B (perché i costruttori padre vengono eseguiti prima dell'inizializzazione del membro della classe ereditata). Dov'è un errore nel mio ragionamento? Cosa succede veramente in questo codice?

EDIT: Sono a conoscenza di altre possibilità per inizializzare questo membro (costruttore di base o assegnazione nel costruttore derivato), ma voglio capire perché è illegale nel modo in cui lo provo? Alcune caratteristiche specifiche del linguaggio C++ o simili? Per favore indicami un paragrafo in C++, se possibile.

risposta

18

Hai bisogno di fare un costruttore per A (che può essere protetto in modo che solo B può chiamare) che m_int inizializza proprio come avete, allora si richiama :A(0) dove avete :m_int(0)

Si potrebbe anche solo impostare m_int = 0 nel corpo del costruttore di B. È accessibile (come si descrive) non è disponibile nella sintassi del costruttore speciale.

+5

Questa è una buona risposta, ma vorrei solo aggiungere qualche spiegazione. Quando usi l'operatore:, stai dicendo al compilatore che prima di fare qualsiasi altra cosa dovrebbe eseguire queste istruzioni. Fondamentalmente stai impostando una variabile prima dell'esecuzione del costruttore genitore (o di qualsiasi altra cosa). Quindi la variabile non esiste. : A(), m_int (0) dovrebbe funzionare pure.Per impostazione predefinita, se non si utilizza:, il compilatore eseguirà il costruttore delle classi di base. In altre parole, se non fai nulla C++ farà cose predefinite per te, se inizi a specificare le cose, si presume che tu sappia cosa stai facendo. –

+0

Hmmm ... Per quanto ne so, il costruttore della classe genitore è sempre eseguito prima di qualsiasi altra inizializzazione, e quindi la variabile 'm_int' esiste già quando sto provando a inizializzarla. Quindi questo non dovrebbe essere il problema ... – Haspemulator

+0

@Haspemulator Sì, esiste già ma è per questo che stai ricevendo l'errore. È già stato inizializzato di default dal costruttore di A. Non è possibile inizializzare nuovamente una variabile nel costruttore di B. Puoi riassegnare come afferma Ben Jackson sopra ('m_int = 0') e questo è tutto a quel punto. – wheaties

4

quello che vuoi è questo:

class A{ 
public: 
    A() : m_int(0); 
    int m_int; 
}; 

in modo che m_int viene inizializzato nel posto giusto.

Edit:

Da un commento di cui sopra, il motivo per il compilatore si lamenta quando si tenta di inizializzare la variabile m_int in B è che è già stato inizializzato dal costruttore di A. Cioè, non puoi ri-inizializzare qualcosa, solo riassegnare. Quindi, puoi riassegnare come dichiarato in precedenza da Ben Jackson o puoi inizializzarlo nel posto giusto.

4

Per creare un'istanza della classe B è necessario prima istanziare un'istanza della classe A. Durante questa istanza m_int viene inizializzato. È dopo l'intializzazione che viene chiamato il costruttore di b, quindi non è possibile reinizializzare lo m_int. Se questo è il vostro obiettivo, allora è possibile implementare un costruttore per A che prende un int e quindi chiamare che nella lista di inizializzazione B s':

class A 
{ 
public: 
    A(int x): m_int(x) {} 
    int m_int; 
}; 

class B: public A 
{ 
public: 
    B(): A(2) {} 
}; 
+0

C'è qualche ragione per cui non è disponibile nella lista di inizializzazione? Sono a conoscenza di altre possibilità per inizializzare questo membro (costruttore di base o assegnazione nel costruttore derivato), ma voglio capire perché è illegale nel modo in cui provo? Alcune caratteristiche specifiche del linguaggio C++ o simili? Per favore indicami un paragrafo in C++, se possibile. – Haspemulator

+0

Sono due cose: le classi derivate creano prima un'istanza delle loro classi di base e i membri vengono inizializzati nell'ordine in cui sono dichiarati, non nell'ordine in cui appaiono nell'elenco di inizializzazione. Pertanto, i membri della base vengono inizializzati per primi e non è possibile inizializzarli nuovamente. –

0

fare un costruttore in A e l'uso B(): A (2) {} contenuto di B(): m_int (0) {} funziona.

Problemi correlati