Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Khi nào nên viết toán tử gán riêng trong C++?

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.