Frage

Was sind die C ++ Regeln für den Oberklassenkonstruktors aus einer Unterklasse rief ein?

Zum Beispiel, ich weiß, in Java, müssen Sie es als die erste Zeile der Unterklasse Konstruktor tun (und wenn Sie dies nicht tun, ein impliziter Aufruf an ein nicht-arg Super Konstruktor angenommen wird - geben Ihnen einen Compiler-Fehler, wenn dass fehlt).

War es hilfreich?

Lösung

Basisklassenkonstruktoren werden automatisch für Sie angerufen, wenn sie kein Argument haben. Wenn Sie einen Oberklassenkonstruktors mit einem Argument aufrufen wollen, müssen Sie die Unterklasse Konstruktor Initialisierungsliste verwenden. Im Gegensatz zu Java, C ++ unterstützt Mehrfachvererbung (für besser oder schlechter), so muss die Basisklasse mit Namen genannt wird, sondern als „super ()“.

class SuperClass
{
    public:

        SuperClass(int foo)
        {
            // do something with foo
        }
};

class SubClass : public SuperClass
{
    public:

        SubClass(int foo, int bar)
        : SuperClass(foo)    // Call the superclass constructor in the subclass' initialization list.
        {
            // do something with bar
        }
};

Weitere Informationen über die Initialisierungsliste Konstruktor hier und hier .

Andere Tipps

In C ++, die kein Argument Konstruktoren für alle übergeordneten Klassen und Member-Variablen sind für Sie aufgerufen, bevor Ihr Konstruktor eingeben. Wenn Sie sie Argumente übergeben möchten, gibt es eine separate Syntax für diesen Namen „Konstruktorverkettung“, die wie folgt aussieht:

class Sub : public Base
{
  Sub(int x, int y)
  : Base(x), member(y)
  {
  }
  Type member;
};

Wenn irgendetwas an dieser Stelle laufen wirft, die Basen / Mitglieder, die vorher Bau abgeschlossen hatten ihre Destruktoren aufgerufen und die Ausnahme erneut ausgelöst, um den Anrufer. Wenn Sie Ausnahmen fangen während verketten wollen, müssen Sie eine Funktion Try-Block verwenden:

class Sub : public Base
{
  Sub(int x, int y)
  try : Base(x), member(y)
  {
    // function body goes here
  } catch(const ExceptionType &e) {
    throw kaboom();
  }
  Type member;
};

In dieser Form ist zu beachten, dass der try-Block ist der Körper der Funktion, anstatt im Inneren des Körpers der Funktion ist; dies ermöglicht es Ausnahmen von impliziten oder expliziten Mitglied und Basisklasse Initialisierungen sowie während der Körper der Funktion geworfen zu fangen. wenn ein Funktion catch-Block wird jedoch nicht eine andere Ausnahme auslösen, wird die Laufzeit der ursprünglichen Fehler erneut auslösen; Ausnahmen bei der Initialisierung kann nicht ignoriert werden.

In C ++ gibt es ein Konzept der Initialisierung Liste Konstruktor, das ist, wo Sie und die Basisklasse Konstruktor aufrufen sollte und wo sollten Sie auch die Datenelemente initialisieren. Die Initialisierungsliste kommt nach dem Konstruktor Signatur nach einem Doppelpunkt und vor dem Körper des Konstrukteurs. Lassen Sie uns sagen, dass wir eine Klasse A haben:


class A : public B
{
public:
  A(int a, int b, int c);
private:
  int b_, c_;
};

Dann B unter der Annahme, einen Konstruktor hat, die ein int, A Konstruktor nimmt wie folgt aussehen:


A::A(int a, int b, int c) 
  : B(a), b_(b), c_(c) // initialization list
{
  // do something
}

Wie Sie sehen können, ist der Konstruktor der Basisklasse in der Initialisierungsliste genannt. Initialisieren der Datenelemente in der Initialisierungsliste, nebenbei gesagt, die Werte für b_ vorzuziehen Zuordnung und c_ im Inneren des Körpers des Konstrukteurs, weil Sie die zusätzlichen Kosten für die Zuordnung speichern.

Beachten Sie, dass Datenelemente immer in der Reihenfolge initialisiert, in der sie in der Klassendefinition deklariert sind, unabhängig von ihrer Reihenfolge in der Initialisierungsliste. Um zu vermeiden, seltsame Fehler, die auftreten können, wenn Sie Ihre Datenelemente voneinander abhängig sind, sollten Sie immer darauf achten, dass die Reihenfolge der Elemente ist die gleiche in der Initialisierungsliste und der Klassendefinition. Aus dem gleichen Grunde muss der Basisklassenkonstruktor das erste Element in der Initialisierungsliste sein. Wenn Sie es ganz weglassen, dann wird der Standard-Konstruktor für die Basisklasse automatisch aufgerufen werden. In diesem Fall ist, wenn die Basisklasse nicht über einen Standardkonstruktor verfügen, erhalten Sie einen Compiler-Fehler.

Jeder erwähnt einen Konstruktoraufruf durch eine Initialisierungsliste, aber niemand sagte, dass ein Konstruktor der übergeordneten Klasse können explizit von der abgeleiteten Mitglied Konstruktor des Körpers bezeichnet werden. Sehen Sie sich die Frage einen Konstruktor der Basisklasse aus einer Unterklasse Konstruktorrumpf , zum Beispiel aufrufen. Der Punkt ist, dass, wenn Sie einen expliziten Aufruf zu einer übergeordneten Klasse oder Superklasse Konstruktor im Körper einer abgeleiteten Klasse zu verwenden, das ist eigentlich nur eine Instanz der übergeordneten Klasse zu schaffen, und es ist der übergeordnete Klasse Konstruktor auf dem abgeleiteten Objekt nicht aufrufe . Der einzige Weg, eine Elternklasse oder Superklasse Konstruktor auf eine abgeleitete Klasse Objekt aufzurufen ist durch die Initialisierungs-Liste und nicht in der abgeleiteten Klasse Konstruktorrumpf. Vielleicht sollte es keine „Oberklassenkonstruktors Aufruf“ bezeichnet werden. Ich habe diese Antwort hier, weil jemand vielleicht verwirren lassen (wie ich).

Die einzige Möglichkeit, Werte zu einem übergeordneten Konstruktor übergeben wird durch eine Initialisierungsliste. Die initilization Liste ist mit einem implementiert. Und dann eine Liste der Klassen und die Werte an, die Klassen-Konstruktor übergeben werden

Class2::Class2(string id) : Class1(id) {
....
}

Denken Sie auch daran, dass, wenn Sie einen Konstruktor, der keine Parameter auf der übergeordneten Klasse nimmt, wird es an den Kindkonstruktors Ausführung automatisch vor aufgerufen werden.

Wenn Sie einen Konstruktor ohne Argumente wird es aufgerufen werden, bevor die abgeleitete Klasse Konstruktor ausgeführt wird.

Wenn Sie einen Basis-Konstruktor mit Argumenten, die Sie explizit haben rufen, dass, wie dies in dem abgeleiteten Konstruktor schreiben:

class base
{
  public:
  base (int arg)
  {
  }
};

class derived : public base
{
  public:
  derived () : base (number)
  {
  }
};

Sie können nicht eine abgeleitete Klasse ohne Aufruf der Eltern Konstruktor in C ++ erstellen. Das geschieht entweder automatisch, wenn es eine nicht arg C'tor ist, es passiert, wenn man die abgeleitete Konstruktor direkt aufrufen, wie oben gezeigt oder Ihr Code wird nicht kompiliert.

Wenn Sie die Standardparameter in Ihrem Basiskonstruktor der Basisklasse haben wird automatisch aufgerufen werden.

using namespace std;

class Base
{
    public:
    Base(int a=1) : _a(a) {}

    protected:
    int _a;
};

class Derived : public Base
{
  public:
  Derived() {}

  void printit() { cout << _a << endl; }
};

int main()
{
   Derived d;
   d.printit();
   return 0;
}

Die Ausgabe ist: 1

CDerived::CDerived()
: CBase(...), iCount(0)  //this is the initialisation list. You can initialise member variables here too. (e.g. iCount := 0)
    {
    //construct body
    }

Niemand erwähnte die Reihenfolge des Konstruktor ruft, wenn eine Klasse von mehreren Klassen ableitet. Die Sequenz ist wie erwähnt, während die Klassen abgeleitet werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top