c++ java - Kann ich einen Konstruktor von einem anderen Konstruktor (do constructor chaining) in C ++ aufrufen?




8 Answers

C ++ 11: Ja!

C ++ 11 und höher hat dieselbe Funktion ( delegierende Konstruktoren genannt ).

Die Syntax unterscheidet sich geringfügig von C #:

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {}
};

C ++ 03: Nein

Leider gibt es keine Möglichkeit, dies in C ++ 03 zu tun, aber es gibt zwei Möglichkeiten, dies zu simulieren:

  1. Sie können zwei (oder mehr) Konstruktoren über Standardparameter kombinieren:

    class Foo {
    public:
      Foo(char x, int y=0);  // combines two constructors (char) and (char, int)
      // ...
    };
    
  2. Verwenden Sie eine Init-Methode, um gemeinsamen Code zu teilen:

    class Foo {
    public:
      Foo(char x);
      Foo(char x, int y);
      // ...
    private:
      void init(char x, int y);
    };
    
    Foo::Foo(char x)
    {
      init(x, int(x) + 7);
      // ...
    }
    
    Foo::Foo(char x, int y)
    {
      init(x, y);
      // ...
    }
    
    void Foo::init(char x, int y)
    {
      // ...
    }
    

Siehe den C ++ - FAQ-Eintrag als Referenz.

c# deutsch

Als C# -Entwickler bin ich gewohnt, Konstruktoren zu durchlaufen:

class Test {
    public Test() {
        DoSomething();
    }

    public Test(int count) : this() {
        DoSomethingWithCount(count);
    }

    public Test(int count, string name) : this(count) {
        DoSomethingWithName(name);
    }
}

Gibt es eine Möglichkeit, dies in C ++ zu tun?

Ich habe versucht, den Klassennamen aufzurufen und das Schlüsselwort 'this' zu verwenden, aber beides schlägt fehl.




Ich glaube, Sie können einen Konstruktor von einem Konstruktor aufrufen. Es wird kompiliert und ausgeführt. Ich habe kürzlich gesehen, dass jemand das macht und es lief sowohl unter Windows als auch unter Linux.

Es macht einfach nicht was du willst. Der innere Konstruktor erstellt ein temporäres lokales Objekt, das gelöscht wird, sobald der äußere Konstruktor zurückgegeben wird. Sie müssten auch andere Konstruktoren sein oder Sie würden einen rekursiven Aufruf erstellen.

Ref: https://isocpp.org/wiki/faq/ctors#init-methoden




In C++11 kann ein Wikipedia :

class Foo  {
     int d;         
public:
    Foo  (int i) : d(i) {}
    Foo  () : Foo(42) {} //New to C++11
};

Darüber hinaus können Mitglieder auch so initialisiert werden.

class Foo  {
     int d = 5;         
public:
    Foo  (int i) : d(i) {}
};

Dadurch sollte die Initialisierungs-Hilfsmethode nicht mehr erstellt werden. Es wird weiterhin empfohlen, keine virtuellen Funktionen in den Konstruktoren oder Destruktoren aufzurufen, um die Verwendung von Membern zu vermeiden, die möglicherweise nicht initialisiert werden.




Nein, in C ++ kann man keinen Konstruktor von einem Konstruktor aufrufen. Was Sie tun können, wie Warren sagte, ist:

  • Überladen Sie den Konstruktor mit verschiedenen Signaturen
  • Verwenden Sie Standardwerte für Argumente, um eine "einfachere" Version verfügbar zu machen

Beachten Sie, dass Sie im ersten Fall die Code-Duplizierung nicht reduzieren können, indem Sie einen Konstruktor von einem anderen Konstruktor aufrufen. Sie können natürlich eine separate private / protected-Methode verwenden, die die gesamte Initialisierung durchführt, und den Konstruktor hauptsächlich mit der Behandlung von Argumenten behandeln lassen.




Wenn Sie Ihre Frage richtig verstehen, fragen Sie, ob Sie mehrere Konstruktoren in C ++ aufrufen können.

Wenn Sie danach suchen, dann ist das nicht möglich.

Sie können sicherlich mehrere Konstruktoren haben, jeder mit eindeutigen Argumentsignaturen, und dann den gewünschten Namen bei der Instanziierung eines neuen Objekts aufrufen.

Sie können am Ende sogar einen Konstruktor mit default-Argumenten haben.

Aber Sie haben möglicherweise nicht mehrere Konstruktoren und rufen sie dann einzeln auf.




Ich würde vorschlagen, eine private friend Methode zu verwenden, die die Anwendungslogik des Konstruktors implementiert und von den verschiedenen Konstruktoren aufgerufen wird. Hier ist ein Beispiel:

Angenommen, wir haben eine Klasse namens StreamArrayReader mit einigen privaten Feldern:

private:
    istream * in;
      // More private fields

Und wir wollen die zwei Konstruktoren definieren:

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...

Wo der zweite einfach den ersten benutzt (und natürlich wollen wir die Umsetzung des ersteren nicht kopieren). Idealerweise würde man gerne so etwas machen wie:

StreamArrayReader::StreamArrayReader(istream * in_stream){
    // Implementation
}

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    StreamArrayReader(&instream);
    instream.close();
}

Dies ist jedoch in C ++ nicht erlaubt. Aus diesem Grund können wir eine private Friend-Methode wie folgt definieren, die implementiert, was der erste Konstruktor tun soll:

private:
  friend void init_stream_array_reader(StreamArrayReader *o, istream * is);

Nun hat diese Methode (weil sie ein Freund ist) Zugriff auf die privaten Felder von o . Dann wird der erste Konstruktor:

StreamArrayReader::StreamArrayReader(istream * is) {
    init_stream_array_reader(this, is);
}

Beachten Sie, dass dadurch nicht mehrere Kopien für die neu erstellten Kopien erstellt werden. Der zweite wird:

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    init_stream_array_reader(this, &instream);
    instream.close();
}

Das heißt, anstatt dass ein Konstruktor einen anderen anruft, rufen beide einen privaten Freund an!




Dieser Ansatz kann für einige Arten von Klassen funktionieren (wenn sich der Zuweisungsoperator "gut" verhält):

Foo::Foo()
{
    // do what every Foo is needing
    ...
}

Foo::Foo(char x)
{
    *this = Foo();

    // do the special things for a Foo with char
    ...
}



Wäre einfacher zu testen, als zu entscheiden :) Versuchen Sie Folgendes:

#include <iostream>

class A {
public:
    A( int a) : m_a(a) {
        std::cout << "A::Ctor" << std::endl;    
    }
    ~A() {
        std::cout << "A::dtor" << std::endl;    
    }
public:
    int m_a;
};

class B : public A {
public:
    B( int a, int b) : m_b(b), A(a) {}
public:
    int m_b;
};

int main() {
    B b(9, 6);
    std::cout << "Test constructor delegation a = " << b.m_a << "; b = " << b.m_b << std::endl;    
    return 0;
}

und kompiliere es mit 98 std: g ++ main.cpp -std = c ++ 98 -o test_1

du wirst sehen:

A::Ctor
Test constructor delegation a = 9; b = 6
A::dtor

damit :)




Related

c++ constructor