2015-12-23 19 views
8

Stavo cercando alcuni test per migliorare le mie conoscenze in C++. Ecco uno degli esercizi: Qual è l'output del seguente programma?C++ - ordine di inizializzazione e di incremento dei membri

#include <iostream> 

class A 
{ 
public: 
    A(int n = 0) : m_i(n) 
    { 
     std::cout << m_i; 
     ++m_i; 
    } 

protected: 
    int m_i; 
}; 

class B : public A 
{ 
public: 
    B(int n = 5) : m_a(new A[2]), m_x(++m_i) { std::cout << m_i; } 

    ~B() { delete [] m_a; } 

private: 
    A m_x; 
    A *m_a; 
}; 

int main() 
{ 
    B b; 
    std::cout << std::endl; 
    return 0; 
} 

Beh, ho provato questo codice, e la risposta è 02002. Vengo qui per avere qualche spiegazione perché non capisco perché il risultato sia 02002. Spiegherò il mio ragionamento, ma alcuni potrebbero dirmi dove sbaglio, per favore?

Chiamiamo "str" ​​la stringa corrente da stampare. Quando l'oggetto b viene creato:

  1. Viene chiamato il costruttore di A. str =>0, m_i =>1
  2. Costruzione di m_a(new A[2]). str =>000
  3. Costruzione di m_x(++m_i). str =>0002, m_i =>3
  4. Ultimo aggiornamento str (nel costruttore B s') => str =>00023

Ecco le mie domande:

  • Perché il valore finale di m_i2 e non 3?
  • Perché la costruzione di m_x(++m_i) è stata preceduta da quella di m_a(new A[2])? Ho provato a scambiare la posizione dell'inizializzazione di m_x e m_a e la risposta è sempre la stessa: 02002.
+0

Poiché 'm_x' è dichiarato * prima *' m_a' nella classe 'B',' B (int n = 5): m_a (nuovo A [2]), m_x (++ m_i) 'è ill- formato e dovrebbe essere 'B (int n = 5): m_x (++ m_i), m_a (nuovo A [2])'. – YSC

+0

@YSC è corretto, almeno, riceverai un sacco di avvertimenti quando compili con gcc (non sono sicuro degli altri) – Danh

+0

@YSC 'B (int n = 5): m_a (nuovo A [2]) , m_x (++ m_i) 'non è mal formato. Forse dovrebbe essere reso mal formato, ma sfortunatamente non lo è. – cpplearner

risposta

12

Perché il valore finale di m_i2 e non 3?

Perché new A[2] crea due istanze separate che non hanno nulla a che fare con *this. m_i dell'istanza b viene incrementato solo in A::A e B::B (due volte).

Se incrementazione di m_i deve essere eseguita sulla stessa istanza (m_i essere un riferimento, per esempio), sarebbe più ragionevole pensare che il valore finale del m_i dovrebbe essere 4 (ci sono due oggetti nell'array - due ulteriori incrementi).

Perché la costruzione di m_x(++m_i) fatto prima di quella di m_a(new A[2])?

Perché the order of initialization depends on the order of declaration of the data members, non l'ordine in cui si scrivono le inizializzazioni nell'elenco di inizializzazione dei membri.

+0

Thx per la risposta! Ho appena capito perché 2 e non 3. Aggiungo anche un altro incremento durante la costruzione di m_x. – Ptiseb

+0

@Ptiseb Alcuni compilatori (MingW e VC) emettono avvisi se si inizializzano i membri in un ordine diverso da quello dichiarato. – Resurrection

4

Quando si crea b la parte A di B viene costruita per prima. Questo dà 0 nell'output. Quindi otteniamo il 2 perché succede prima dal momento che m_x è elencato per primo nella classe. Poiché m_i è 1 dalla parte A di B in fase di costruzione ++m_i corrisponde a 2 e ora abbiamo 02. Quindi viene eseguito m_a(new A[2]) che ci dà 2 0 (uno per ogni membro dell'array). Questo ci mette a 0200. Otteniamo quindi il 2 finale da { std::cout << m_i; } poiché m_i è ancora 2 da m_x(++m_i).

Problemi correlati