2015-12-23 18 views
8

Ich suchte nach einigen Tests, um meine C++ Kenntnisse zu verbessern. Hier ist eine der Übungen: Was ist die Ausgabe des folgenden Programms?C++ - Reihenfolge der Mitglieder Initialisierung und Inkrementierung

#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; 
} 

Nun habe ich versucht, diesen Code, und die Antwort ist 02002. Ich komme hierher, um eine Erklärung zu haben, weil ich nicht verstehe, warum 02002 das Ergebnis ist. Ich werde meine Argumentation erklären, aber könnten mir einige sagen, wo liege ich falsch?

Lassen Sie uns "str" ​​die aktuelle Zeichenfolge zum Drucken nennen. Wenn das b Objekt gebaut wird:

  1. Der Konstruktor von A aufgerufen. str =>01
  2. m_a(new A[2]). str =>000
  3. Konstruktion von m_x(++m_i). str =>0002, m_i =>3
  4. Letzte Aktualisierung von str (in B ‚s Konstruktor) => str =>00023

Hier sind meine Fragen:

  • Warum ist der Endwert von m_i2 und nicht 3?
  • Warum wird der m_x(++m_i) vor dem von m_a(new A[2]) gebaut? Ich habe versucht, die Position der Initialisierung von m_x und m_a auszutauschen und die Antwort ist immer noch die gleiche: 02002.
+0

Da 'm_x' in der' B' Klasse * vor * 'm_a' deklariert ist,' B (int n = 5): m_a (neu A [2]), m_x (++ m_i) 'ist krank- gebildet und sollte 'B (int n = 5) sein: m_x (++ m_i), m_a (neu A [2])'. – YSC

+0

@YSC ist korrekt, zumindest werden Sie eine Menge Warnung bekommen, wenn Sie mit gcc kompilieren (ich bin mir nicht sicher über die anderen) – Danh

+0

@YSC 'B (int n = 5): m_a (neu A [2]) , m_x (++ m_i) 'ist nicht schlecht gebildet. Vielleicht sollte es schlecht gemacht werden, aber leider nicht. – cpplearner

Antwort

12

Warum ist der Endwert m_i2 und nicht 3?

Weil new A[2] zwei separate Instanzen erstellt, die nichts mit *this zu tun haben. m_i der b Instanz wird nur in A::A und B::B (zweimal) inkrementiert.

Wenn Inkrementierung m_i sollte auf derselben Instanz durchgeführt werden (m_i eine Referenz, zum Beispiel), wäre es sinnvoll sein, zu denken, dass der endgültige Wert von m_i4 sein sollte (es gibt zwei Objekte in dem Array - zwei zusätzliche Inkremente).

Warum ist der Bau von m_x(++m_i) vor dem von m_a(new A[2]) getan?

Da the order of initialization depends on the order of declaration of the data members, nicht die Reihenfolge, in der Sie Initialisierungen in der Memberinitialisierungsliste schreiben.

+0

Thx für die Antwort! Ich habe gerade verstanden warum 2 und nicht 3. Ich füge auch noch eine Inkrementierung während der Konstruktion von m_x hinzu. – Ptiseb

+0

@Ptiseb Einige Compiler (MingW und VC) geben Warnungen aus, wenn Sie Member in anderer Reihenfolge initialisieren, als Sie sie deklariert haben. – Resurrection

4

Wenn Sie b konstruieren, wird zuerst der A Teil von B erstellt. Dies gibt die 0 in der Ausgabe. Dann erhalten wir die 2, weil m_x(++m_i) zuerst passiert, seit m_x zuerst in der Klasse aufgeführt ist. Da m_i 1 ist aus A Teil von B wird ++m_i2 konstruiert und jetzt haben wir 02. Dann wird m_a(new A[2]) ausgeführt, was uns 2 0 gibt (eins für jedes Mitglied des Arrays). Das bringt uns auf 0200. Wir erhalten dann das endgültige 2 von { std::cout << m_i; }, da m_i immer noch 2 von m_x(++m_i) ist.

Verwandte Themen