2010-10-21 4 views
18

Ich habe eine Frage zur Initialisierung geerbter Member im Konstruktor der abgeleiteten Klasse. Beispielcode:C++: Initialisierung des geerbten Felds

class A 
    { 
public: 
    int m_int; 
    }; 

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

Dieser Code gibt mir die folgende Ausgabe:

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

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

ich vermute ich, warum dies geschieht? m_int sollte Mitglied von B sein, und die übergeordnete Klasse A sollte bereits initialisiert werden, wenn die Initialisierung von m_int in B geschieht (da Elternkonstruktoren vor der Memberinitialisierung der geerbten Klasse ausgeführt werden). Wo ist ein Fehler in meiner Argumentation? Was passiert wirklich in diesem Code?

EDIT: Ich kenne andere Möglichkeiten, dieses Mitglied (Basiskonstruktor oder Zuordnung in abgeleiteten Konstruktor) zu initialisieren, aber ich möchte verstehen, warum ist es illegal in der Art, wie ich es versuche? Einige spezielle C++ - Sprachfunktionen oder solche? Bitte weisen Sie mich nach Möglichkeit auf einen Absatz im C++ - Standard hin.

Antwort

18

Sie benötigen einen Konstruktor für A machen (es so nur B geschützt werden kann, kann es nennen), die m_int initialisiert wie Sie haben, Sie dann :A(0) aufrufen, wo Sie :m_int(0)

Sie können auch festlegen nur m_int = 0 haben im Körper von B's Konstrukteur. Es ist zugänglich (wie Sie beschreiben), es ist einfach nicht in der speziellen Konstruktorsyntax verfügbar.

+5

Dies ist eine gute Antwort, aber ich möchte nur eine Erklärung hinzufügen. Wenn Sie den Operator: verwenden, sagen Sie dem Compiler, dass er diese Anweisungen ausführen soll, bevor er etwas anderes ausführt. Grundsätzlich setzen Sie eine Variable, bevor der übergeordnete Konstruktor (oder irgendetwas anderes) ausgeführt wurde. Daher existiert die Variable nicht. : A(), m_int (0) sollte auch funktionieren.Wenn Sie nicht: verwenden, führt der Compiler standardmäßig den Basisklassenkonstruktor aus. Mit anderen Worten, wenn Sie nichts tun, wird C++ Standard-Dinge für Sie tun, wenn Sie anfangen, Dinge zu spezifizieren, geht es davon aus, dass Sie wissen, was Sie tun. –

+0

Hmmm ... Soweit ich weiß, wird der Konstruktor der Elternklasse immer vor allen anderen Initialisierungen ausgeführt, und daher existiert die Variable 'm_int' bereits, wenn ich versuche, sie zu initialisieren. Also sollte das nicht das Problem sein ... – Haspemulator

+0

@Haspemulator Ja, es existiert bereits, aber deshalb erhalten Sie den Fehler. Es wurde bereits standardmäßig vom Konstruktor von A initialisiert. Sie können eine Variable in Bs Konstruktor nicht neu initialisieren. Sie können neu zuweisen, wie Ben Jackson oben sagt ('m_int = 0') und das ist ungefähr zu diesem Zeitpunkt. – wheaties

4

Was Sie wollen, ist dies:

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

so dass m_int wird an der richtigen Stelle initialisiert.

Edit:

Aus einem Kommentar oben, der Grund der Compiler beschwert sich, wenn Sie versuchen, die m_int Variable in B zu initialisieren ist, dass es bereits durch den Konstruktor A initialisiert wurde. Das heißt, Sie können etwas nicht neu initialisieren, sondern nur neu zuweisen. Sie können also wie Ben Jackson oben angeben, oder Sie können an der richtigen Stelle initialisieren.

4

Um eine Instanz der Klasse B zu erstellen, instanziieren Sie zuerst eine Instanz der Klasse A. Während dieser Instanziierung wird m_int initialisiert. Nach der Initialisierung wird der Konstruktor b aufgerufen, sodass Sie m_int nicht reinitialisieren können. Wenn das Ihr Ziel ist, dann können Sie einen Konstruktor für A implementieren, die einen int nimmt und dann, dass rufen in B ‚s Initialisierungsliste:

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

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

Gibt es einen Grund, warum es in der Initialisierungsliste nicht verfügbar ist? Mir sind andere Möglichkeiten bekannt, dieses Element zu initialisieren (Basiskonstruktor oder Zuweisung in abgeleitetem Konstruktor), aber ich möchte verstehen, warum es in der Art, wie ich es versuche, illegal ist? Einige spezielle C++ - Sprachfunktionen oder solche? Bitte weisen Sie mich nach Möglichkeit auf einen Absatz im C++ - Standard hin. – Haspemulator

+0

Es gibt zwei Dinge - abgeleitete Klassen instanziieren zuerst ihre Basisklassen und Mitglieder werden in der Reihenfolge initialisiert, in der sie deklariert sind, nicht in der Reihenfolge, in der sie in der Initialisierungsliste erscheinen. Daher werden die Mitglieder der Basis zuerst initialisiert und Sie können sie nicht erneut initialisieren. –

0

einen Konstruktor machen in A und Verwendung B(): A (2) {} ohne B(): m_int (0) {} funktioniert.