Chúng ta sẽ xem khi nào cần tạo toán tử gán (assignment operator) riêng trong C++. Nếu một lớp không có con trỏ, thì không cần tạo toán tử gán và constructor sao chép. Trình biên dịch C++ tự tạo constructor sao chép và toán tử gán cho mỗi lớp. Nếu các toán tử đó không đủ, ta phải tự viết toán tử gán.
Ví dụ
#include<iostream>
using namespace std;
class MyClass {
// không có toán tử gán hoặc constructor sao chép do người dùng định nghĩa
int *ptr;
public:
MyClass(int x = 0) {
ptr = new int(x);
}
void setValue(int x) {
*ptr = x;
}
void print() {
cout << *ptr << endl;
}
};
int main() {
MyClass ob1(50);
MyClass ob2;
ob2 = ob1;
ob1.setValue(100);
ob2.print();
}
Kết quả
100
Trong main(), ta đặt giá trị x dùng setValue() cho ob1. Giá trị cũng phản ánh trong ob2; Loại thay đổi không mong muốn này có thể gây lỗi. Không có toán tử gán do người dùng định nghĩa, nên trình biên dịch tự tạo. Ở đây nó sao chép con trỏ của vế phải sang vế trái. Cả hai con trỏ trỏ cùng một vị trí.
Để giải quyết, có hai cách: tạo toán tử gán private giả (dummy) để ngăn sao chép đối tượng, hoặc tự viết toán tử gán.
Ví dụ
#include<iostream>
using namespace std;
class MyClass {
int *ptr;
public:
MyClass(int x = 0) {
ptr = new int(x);
}
void setValue(int x) {
*ptr = x;
}
void print() {
cout << *ptr << endl;
}
MyClass &operator=(const MyClass &ob2) {
// Kiểm tra tự gán
if(this != &ob2)
*ptr = *(ob2.ptr);
return *this;
}
};
int main() {
MyClass ob1(50);
MyClass ob2;
ob2 = ob1;
ob1.setValue(100);
ob2.print();
}
Kết quả
50
Ở đây toán tử gán tạo bản sao sâu (deep copy) và lưu con trỏ riêng. Một lưu ý: phải kiểm tra tự tham chiếu (self-assignment) nếu không toán tử gán có thể thay đổi giá trị đối tượng hiện tại.