Implementieren von Klassenkonstruktoren in C++

Jinku Hu 12 Oktober 2023
  1. Was sind Konstruktoren und wie funktionieren sie in C++?
  2. Implementieren mehrerer Klassenkonstruktoren mithilfe von Überladung in C++
Implementieren von Klassenkonstruktoren in C++

In diesem Artikel wird vorgestellt, wie Klassenkonstruktoren in C++ implementiert werden.

Was sind Konstruktoren und wie funktionieren sie in C++?

Konstruktoren sind spezielle Memberfunktionen, die definieren, wie das Klassenobjekt initialisiert werden soll. Konstruktoren initialisieren im Allgemeinen Datenmember der Klasse und werden ausgeführt, wenn ein Klassenobjekt erstellt wird. Einige Besonderheiten der Konstruktorfunktionen sind, dass sie denselben Namen wie die Klasse selbst haben und keinen Rückgabetyp haben können. Normalerweise hat eine Klasse mehrere Konstruktoren, die sich gegenseitig überladen, aber sie müssen eine unterschiedliche Anzahl oder Typen von Parametern haben.

Beachten Sie, dass Konstruktoren in jeder leicht komplexen Klasse vom Benutzer oft explizit angegeben werden. Der Standardkonstruktor wird jedoch automatisch vom Compiler generiert, wenn der Benutzer keine Konstruktoren definiert. Der Standardkonstruktor ist im Allgemeinen derjenige, der keine Argumente akzeptiert und für die Standardinitialisierung der Klasse aufgerufen wird. Beachten Sie jedoch, dass ein vom Compiler generierter Standardkonstruktor formal als synthetisierter Standardkonstruktor bezeichnet wird. Letzteres wird speziell für jede Klasse entsprechend ihren Datenmembern abgeleitet und initialisiert die Member mit dem klasseninternen Initialisierer oder mit dem Standardwert. Somit sind automatisch generierte Konstruktoren nicht die universelle Lösung, funktionieren aber für einfache Klassenstrukturen korrekt.

Im folgenden Beispiel haben wir eine Klasse MyClass1 mit zwei Konstruktoren definiert. Beachten Sie, dass der erste keine Argumente akzeptiert, was bedeutet, dass es sich um einen Standardkonstruktor handelt, aber wir haben trotzdem ein default-Schlüsselwort angegeben. Letzteres zeigt dem Compiler an, dass dieser spezifische Konstruktor der Standardkonstruktor sein sollte. Im Allgemeinen generiert ein Compiler keinen Standardkonstruktor, wenn der Benutzer einen Konstruktor definiert. In diesem Fall sollte ein Benutzer explizit die Bezeichnung default für die angegebene Konstruktorfunktion anfordern.

Der zweite Konstruktor von MyClass1 nimmt einen einzelnen string-Wert als Argument und initialisiert damit den name-Datenmember. Es druckt das spezielle String-Literal an den cout-Stream nur, um den Zeitpunkt der Funktionsausführung für die Beobachtung sichtbar zu machen. m2-Objekterstellung löst die Konstruktor-Erstellung aus. Das Objekt m1 wird mit dem Standardkonstruktor initialisiert, und da der Compiler den letzteren selbst generiert, sehen wir keinen gedruckten String im Stream cout.

#include <iostream>
#include <utility>

using std::cout;
using std::endl;
using std::string;

class MyClass1 {
 private:
  string name;
  string nickname;

 public:
  MyClass1() = default;
  explicit MyClass1(string n) : name(std::move(n)) {
    cout << "Constructor 1 is called" << endl;
  };

  string getName() { return name; }

  string getNickname() { return nickname; }

  ~MyClass1() { cout << "Destructor is called" << endl; }
};

int main() {
  MyClass1 m1{};
  cout << m1.getName() << endl;
  cout << m1.getNickname() << endl;
  cout << "------------------" << endl;

  string n1("Maude");
  MyClass1 m2(n1);
  cout << m2.getName() << endl;
  cout << m2.getNickname() << endl;
  cout << "------------------" << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

------------------
Constructor 1 is called
Maude

------------------
Destructor is called
Destructor is called

Implementieren mehrerer Klassenkonstruktoren mithilfe von Überladung in C++

MyClass1 hat das zweite string-Datenelement namens nickname. Angenommen, wir erstellen einen anderen Konstruktor, der einen einzelnen string-Wert nimmt und definiert, um den nickname zu initialisieren. In diesem Fall gibt der Compiler den Fehler aus, dass wir die Funktionen nicht mit denselben Parametern überladen können. Wir müssen also einen anderen Konstruktor definieren, z. B. haben wir den Konstruktor ausgewählt, der zwei string-Referenzen nimmt und beide Datenelemente initialisiert. Wenn der folgende Codeausschnitt ausgeführt wird, können wir sehen, dass der zweite Konstruktor ausgeführt wurde.

Konstruktoren haben weitaus detailliertere Eigenschaften, und wir haben in diesem Artikel nur die wichtigsten Funktionen vorgestellt. Andere spezielle Funktionen enthalten das Wort -constructor in ihrem Namen, wie move-constructor und copy-constructor. Diese beiden sind Teil von speziellen Operationen, die zusammenfassend Kopierkontrolle genannt werden. Beachten Sie, dass Destruktoren das Gegenteil von dem ausführen, was die Konstruktoren tun. Sie geben nämlich die Klassenmitglieder frei und werden normalerweise automatisch aufgerufen, wenn das Objekt den Gültigkeitsbereich verlässt. Mit den gegebenen Code-Schnipseln kann man das Konstruktor-Destruktor-Aufrufverhalten leicht beobachten.

#include <iostream>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;

class MyClass1 {
 private:
  string name;
  string nickname;

 public:
  MyClass1() = default;
  explicit MyClass1(string n) : name(std::move(n)) {
    cout << "Constructor 1 is called" << endl;
  };

  // ERROR: Does not Compile
  //    MyClass1(string nk) : nickname(nk) {
  //        cout << "Constructor 3 is called" << endl;
  //    };
  MyClass1(string &n, string &nk) : name(n), nickname(nk) {
    cout << "Constructor 2 is called" << endl;
  };

  string getName() { return name; }

  string getNickname() { return nickname; }

  ~MyClass1() { cout << "Destructor is called" << endl; }
};

int main() {
  string n1("Maude");
  string n2("Bibi");

  MyClass1 m4(n1, n2);
  cout << m4.getName() << endl;
  cout << m4.getNickname() << endl;
  cout << "------------------" << endl;

  return EXIT_SUCCESS;
}

Ausgabe:

Constructor 2 is called
Maude
Bibi
------------------
Destructor is called
Destructor is called
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Verwandter Artikel - C++ Class