Implementar sobrecarga de operador de atribuição em C++
Este artigo explicará vários métodos de como implementar a sobrecarga do operador de atribuição em C++.
Use operador de atribuição de cópia
para implementar o operador de atribuição sobrecarregado em C++
C++ fornece o recurso para sobrecarregar os operadores, uma maneira comum de chamar funções personalizadas quando um operador integrado é chamado em classes específicas. Essas funções devem ter um nome especial começando com operador
seguido pelo próprio símbolo de operador específico. Por exemplo, um operador de atribuição personalizada pode ser implementado com a função chamada operator=
. O operador de atribuição geralmente deve retornar uma referência ao seu operando à esquerda. Observe que, se o usuário não definir explicitamente o operador de atribuição de cópia, o compilador gerará um automaticamente. A versão gerada é bastante capaz quando a classe não contém nenhum membro de dados alocado manualmente na memória heap. Ele pode até mesmo lidar com os membros do array atribuindo cada elemento aos membros do objeto correspondente. Embora, ele tenha deficiências ao lidar com membros de dados de memória dinâmica, conforme mostrado no código de exemplo a seguir.
#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);
}
Resultado:
Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Liam White
O código acima define apenas construtor de cópia
explicitamente, o que resulta em comportamento incorreto quando o conteúdo do objeto P1
é atribuído ao objeto P3
. Observe que a segunda chamada à função P1.renamePerson
não deveria ter modificado os membros de dados do objeto P3
, mas mudou. A solução para isso é definir um operador de atribuição sobrecarregado, ou seja, operador de atribuição de cópia. O próximo trecho de código implementa a versão da classe Person
que pode copiar e atribuir os dois objetos da mesma classe corretamente. Observe, porém, que a instrução if
na função de atribuição de cópia garante que o operador funcione corretamente mesmo quando o objeto é atribuído a ele mesmo.
#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);
}
Resultado:
Buddy Rich
Buddy Rich
Jay Roach
Buddy Rich
Jay Roach
Jay Roach
Liam White
Jay Roach
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