Implementieren der Überladung von Zuweisungsoperatoren in C++

Jinku Hu 12 Oktober 2023
Implementieren der Überladung von Zuweisungsoperatoren in C++

In diesem Artikel werden verschiedene Methoden zum Implementieren der Überladung von Zuweisungsoperatoren in C++ erläutert.

Verwenden Sie Kopierzuweisungsoperator, um den überladenen Zuweisungsoperator in C++ zu implementieren

C++ bietet die Funktion zum Überladen von Operatoren, eine übliche Methode zum Aufrufen benutzerdefinierter Funktionen, wenn ein integrierter Operator für bestimmte Klassen aufgerufen wird. Diese Funktionen sollten einen speziellen Namen haben, der mit operator gefolgt vom spezifischen Operatorsymbol selbst beginnt. Beispielsweise kann ein benutzerdefinierter Zuweisungsoperator mit der Funktion operator= implementiert werden. Der Zuweisungsoperator sollte im Allgemeinen einen Verweis auf seinen linken Operanden zurückgeben. Beachten Sie, dass der Compiler automatisch einen generiert, wenn der Benutzer den Operator für die Kopierzuweisung nicht explizit definiert. Die generierte Version ist durchaus in der Lage, wenn die Klasse keine Datenelemente enthält, die manuell im Heapspeicher zugewiesen wurden. Es kann sogar die Array-Mitglieder behandeln, indem jedes Element den entsprechenden Objektelementen zugewiesen wird. Es weist jedoch Mängel beim Umgang mit dynamischen Speicherdatenelementen auf, wie im folgenden Beispielcode gezeigt.

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

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

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

Ausgabe:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Liam White

Der obige Code definiert nur Kopierkonstruktor explizit, was zu einem falschen Verhalten führt, wenn dem Objekt P3 Objektinhalte P1 zugewiesen werden. Beachten Sie, dass der zweite Aufruf der Funktion P1.renamePerson die Datenelemente des Objekts P3 nicht hätte ändern dürfen, dies jedoch tat. Die Lösung hierfür besteht darin, einen überladenen Zuweisungsoperator zu definieren, d. H. Einen Kopierzuweisungsoperator. Das nächste Code-Snippet implementiert die Version der Klasse Person, die kopieren kann, um die beiden Objekte derselben Klasse korrekt zuzuweisen. Beachten Sie jedoch, dass die Anweisung if in der Kopierzuweisungsfunktion garantiert, dass der Operator auch dann ordnungsgemäß funktioniert, wenn das Objekt sich selbst zugewiesen ist.

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

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

class Person {
 public:
  Person() {
    name = new string;
    surname = new string;
  };
  Person(string n, string s) {
    name = new string(std::move(n));
    surname = new string(std::move(s));
  }
  Person(Person &p) {
    name = new string(*p.name);
    surname = new string(*p.surname);
  }

  ~Person() {
    delete name;
    delete surname;
  }

  Person &operator=(const Person &p) {
    if (this != &p) {
      *name = *(p.name);
      *surname = *(p.surname);
    }
    return *this;
  }

  void renamePerson(const string &n, const string &s) {
    name->assign(n);
    surname->assign(s);
  };

  void printPerson() { cout << *name << " " << *surname; }

 private:
  string *name;
  string *surname;
};

int main() {
  Person P1("Buddy", "Rich");
  Person P2 = P1;

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  P1.renamePerson("Jay", "Roach");

  P1.printPerson();
  cout << endl;
  P2.printPerson();
  cout << endl;

  Person P3;
  P3 = P1;
  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  P1.renamePerson("Liam", "White");

  P1.printPerson();
  cout << endl;
  P3.printPerson();
  cout << endl;

  exit(EXIT_SUCCESS);
}

Ausgabe:

Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Jay Roach
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