Implementar la sobrecarga del operador de asignación en C++

Jinku Hu 12 octubre 2023
Implementar la sobrecarga del operador de asignación en C++

Este artículo explicará varios métodos de cómo implementar la sobrecarga del operador de asignación en C++.

Utilice el operador de asignación de copia para implementar el operador de asignación sobrecargado en C++

C++ proporciona la función de sobrecargar operadores, una forma común de llamar a funciones personalizadas cuando se llama a un operador integrado en clases específicas. Estas funciones deben tener un nombre especial que comience con operador seguido del símbolo del operador específico. Por ejemplo, se puede implementar un operador de asignación personalizado con la función denominada operador =. El operador de asignación generalmente debe devolver una referencia a su operando de la izquierda. Tenga en cuenta que si el usuario no define explícitamente el operador de asignación de copia, el compilador genera uno automáticamente. La versión generada es bastante capaz cuando la clase no contiene ningún miembro de datos asignado manualmente en la memoria del montón. Incluso puede manejar los miembros del array asignando cada elemento a los miembros de objeto correspondientes. Sin embargo, tiene deficiencias cuando se trata de miembros de datos de memoria dinámica, como se muestra en el siguiente código de ejemplo.

#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);
}

Producción :

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

El código anterior define sólo constructor de copia explícitamente, lo que da como resultado un comportamiento incorrecto cuando el contenido del objeto P1 se asigna al objeto P3. Tenga en cuenta que la segunda llamada a la función P1.renamePerson no debería haber modificado los miembros de datos del objeto P3, pero lo hizo. La solución a esto es definir un operador de asignación sobrecargado, es decir, un operador de asignación de copia. El siguiente fragmento de código implementa la versión de la clase Person que puede copiar y asignar correctamente los dos objetos de la misma clase. Sin embargo, observe que la instrucción if en la función de copia-asignación garantiza que el operador funciona correctamente incluso cuando el objeto está asignado a sí mismo.

#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);
}

Producción :

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

Artículo relacionado - C++ Class