Con trỏ this trong C++

Ở bài học trước chúng ta đã tìm hiểu về con trỏ trong C++. Trong bài học hôm nay chúng ta sẽ cùng tìm hiểu về con trỏ this trong C++. Vậy con trỏ this có gì đặc biệt. Khi nào thì cần dùng con trỏ this. Chúng ta sẽ cùng tìm hiểu trong nội dung sau đây.

1. Con trỏ this trong C++

This là một con trỏ đặc biệt dùng để trỏ đến địa chỉ của đối tượng hiện tại. Như vậy để truy cập đến các thuộc tính, phương thức của đối tượng hiện tại thì ta sẽ sử dụng con trỏ this. Hãy xem ví dụ dưới đây.

Ví dụ
#include <iostream>  
using namespace std;  
class NhanVien { 
    int msnv;    
    string ten;
    int tuoi;
    public:  
       void setData(int msnv, string ten, int tuoi) {  
            this->msnv = msnv;    
            this->ten = ten;    
            this->tuoi = tuoi; 
       }    
       void showData() {
            cout << "Ten nhan vien: " << this->ten << endl;
            cout << "Ma so nhan vien: " << this->msnv << endl;
            cout << "Tuoi: " << this->tuoi << endl;
       }    
};

Trong ví dụ này mình đã tạo ra ba thuộc tính để lưu trữ thông tin của một nhân viên đó là: manv, ten, tuoi. Ngoài ra mình có tạo thêm phương thức setData() dùng để gán dữ liệu cho sinh viên, và showData() dùng để hiển thị dữ liệu.

Trong phương thức setData() mình đã sử dụng từ khóa this->ten_thuoc_tinh để thực hiện phép gán dữ liệu cho các thuộc tính, còn ở phương thức showData() mình cũng sử dụng cú pháp tương tự để hiển thị dữ liệu của các thuộc tính. Như vậy công dụng của từ khóa this chính là một con trỏ và trỏ đến địa chỉ của đối tượng hiện tại.

Câu hỏi đặt ra là đối tượng hiện tại tại là gì? Để hiểu rõ hơn thì hãy xem đoạn code sử dụng class trên như sau:

Ví dụ
int main() { 
    // Nhan vien 1
    NhanVien n1 =  NhanVien();
    n1.setData(111231, "Nguyen Van A", 24);
    n1.showData();    
    
    // Nhan vien 2
    NhanVien n2 =  NhanVien();
    n2.setData(111232, "Nguyen Van B", 25);
    n2.showData();
    return 0;  
}

Trong ví dụ này mình đã tạo ra hai đối tượng sinh viên đó là n1n2, và con trỏ this của n1 sẽ trỏ đến chính đối tượng n1, con trỏ this của n2 sẽ trỏ đến chính đối tượng n2, đây ta gọi là đối tượng hiện tại.

Lưu ý: Trong các phương thức bình thường (không phải hàm khởi tạo) nếu bạn sử dụng tên của biến thì sẽ có hai trường hợp xảy ra.

  • Nếu biến đó không tôn tại trong phương thức  mà nó lại trùng với tên thuộc tính thì mặc nhiên nó sẽ hiểu đó là thuộc tính.
  • Nếu biến đó có khai báo trong phương thức thì ta sẽ hiểu đó là biến bình thường, không phải là thuộc tính.

2. Một ví dụ khác về con trỏ this

Bạn hãy xem ví dụ dưới đây, đây là một ví dụ mình viết lại ở phần 1 và có một chút thay đổi.

Ví dụ
#include <iostream>  
using namespace std;  
class NhanVien { 
    int msnv;    
    string ten;
    int tuoi;
    public:  
       NhanVien(int msnv, string ten, int tuoi) {  
            cout << "Trong ham xay dung: " << endl;
            cout << "   msnv: " << msnv << endl;
            cout << "   ten: " << ten << endl;
            cout << "   Tuoi: " << tuoi << endl;
            msnv = msnv;    
            ten = ten;    
            tuoi = tuoi; 
       }    
       void HienThi() {
            cout << "Ham in thong tin cua doi tuong nhan vien: " << endl;
            cout << ten << endl;
            cout << "   Ma so nhan vien: " << msnv << endl;
            cout << "   Tuoi: " << tuoi << endl;
       }    
};  
  
int main() {  
    NhanVien n1 =  NhanVien(111231, "Nguyen Van A", 25);    
    n1.HienThi();    
    return 0;  
}

Và kết quả sau khi thực thi chương trình trên như sau:

Đây là một kết quả mà chúng ta không hề mong đợi đúng không? Mình mong muốn in ra thông tin của sinh viên nhưng có vẻ như nó in ra một dãy số nào đó, có thể là một địa chỉ trong một ô nhớ nào đó.

Các bạn mới học chắc thắc mắc tại sao chương trình lại ra kết quả như vậy? Mình xin được giải thích kết quả của chương trình trên như sau:

  • Khi chúng ta khai báo tên của tham số hàm trùng tên với dữ liệu thành viên của lớp, thì bên trong hàm xây dựng chương trình hiểu là biến tham số chứ không phải dữ liệu thành viên của lớp
  • Như vậy ở ví dụ trên, bên trong thân hàm xây dựng ta gán msnv = msnv, ten = ten, tuoi = tuoi, thì chương trình hiểu mssv, ten, tuoi chính là biến truyền vào từ hàm xây dựng, chính vì vậy nó không cập nhật vào các thuộc tính của đối tượng.
  • Khi các dữ liệu thành viên như msnv, ten, tuoi không được khỏi tạo giá trị nó sẽ có giá trị tự động cho chương trình tạo ra mà chúng ta không hề biết trước

Con trỏ this trong C++ giúp chúng ta giải quyết được vấn về trên. Chúng ta sẽ dùng con trỏ this trong ví dụ trên như sau:

Ví dụ
#include <iostream>  
using namespace std;  
class NhanVien { 
    int msnv;    
    string ten;
    int tuoi;
    public:  
       NhanVien(int msnv, string ten, int tuoi) {  
            cout << "Trong ham xay dung: " << endl;
            cout << "   msnv: " << msnv << endl;
            cout << "   ten: " << ten << endl;
            cout << "   Tuoi: " << tuoi << endl;
            this->msnv = msnv;    
            this->ten = ten;    
            this->tuoi = tuoi; 
       }    
       void HienThi() {
            cout << "Ham in thong tin cua doi tuong nhan vien: " << endl;
            cout << ten << endl;
            cout << "   Ma so nhan vien: " << msnv << endl;
            cout << "   Tuoi: " << tuoi << endl;
       }    
};  
  
int main() {  
    NhanVien n1 =  NhanVien(111231, "Nguyen Van A", 25);    
    n1.HienThi();    
    return 0;  
}

Và kết quả sau khi thực thi chương trình trên như sau:

Kết quả trên đúng như kết quả của chúng ta mong đợi rồi nhé. :)

Như vậy con trỏ this trong C++ dùng để tham chiếu đến thể hiện hiện tại của lớp. Con trỏ this có thể sử dụng trong 3 cách như sau:

  • Nó có thể được sử dụng để truyền đối tượng hiện tại làm tham số cho phương thức khác.
  • Nó có thể được sử dụng để tham chiếu đến thể hiện hiện tại của lớp (như ở ví dụ trên).
  • Nó có thể được sử dụng để khai báo các chỉ mục.

2. Thêm một vài ví dụ với this

Bây giờ ta sẽ thực hành thêm một vài ví dụ nữa để các bạn hiểu được con trỏ this, nó sẽ rất quan trọng khi các bạn làm việc với đối tượng  trong OOP.

Ví dụ 1: Chúng ta sẽ cùng lấy một ví dụ đơn giản khác về sử dụng con trỏ this trong trường hợp tên của tham số trùng tên với dữ liệu thành viên như sau:

Ví dụ
#include <iostream>  
using namespace std; 
  
class TestPointer { 
    private: 
       int a; 
       int b;
    public: 
       void ThietLapGiaTri(int a, int b) { 
           this->a = a; 
           this->b = b;
       } 
       void HienThi() { 
           cout << "Gia tri cua a: " << a << endl;
           cout << "Gia tri cua b: " << b << endl;
       } 
    }; 
  
int main() { 
   TestPointer p; 
   int a = 10;
   int b = 20;
   p.ThietLapGiaTri(a, b);
   p.HienThi(); 
   return 0; 
}

Và kết quả sau khi thực thi chương trình trên như sau:

Ví dụ 2: Chúng ta cùng xem xét ví dụ sử dụng con trỏ để trả về tham chiếu cho đối tượng gọi

Ví dụ
#include<iostream> 
using namespace std; 
  
class TestPointer { 
    private: 
      int a; 
      int b; 
    public: 
      TestPointer(int a, int b) { 
          this->a = a; 
          this->b = b; 
      } 
      TestPointer &ThietLapGiaTriA(int x) {
          a = x; 
          return *this; 
      } 
      TestPointer &ThietLapGiaTriB(int y) { 
          b = y; 
          return *this; 
          
      } 
      void HienThi() { 
          cout << "   Gia tri a = " << a << endl;
          cout << "   Gia tri b = " << b << endl; 
      } 
}; 
  
int main() {
  cout << "----------Thong tin doi tuong p-----------" << endl;
  TestPointer p(4, 8); 
  p.HienThi();
  cout << "Thong tin doi tuong p sau khi thiet lap gia tri" << endl;
  p.ThietLapGiaTriA(10);
  p.ThietLapGiaTriB(20); 
  //Hoac chung ta cung co the viet p.ThietLapGiaTriA(10).ThietLapGiaTriB(20);
  p.HienThi();
  
  cout << endl << "----------Thong tin doi tuong p2-----------" << endl;
  TestPointer p2(4, 5); 
  p2.HienThi();
  p2.ThietLapGiaTriA(55).ThietLapGiaTriB(67);
  cout << "Thong tin doi tuong p2 sau khi thiet lap gia tri" << endl;
  p2.HienThi();
  
  return 0; 
} 

Và kết quả sau khi thực thi chương trình trên như sau:

3. Kết luận

Như vậy chúng ta đã tìm hiểu xong con trỏ this trong C++ là gì rồi. Ở bài này các bạn chỉ cần nhớ đơn giản đó là con trỏ this tham chiếu đến đối tượng hiện tại của lớp.

Mình khuyến khích các bạn nên đặt tham số của hàm xây dựng trùng tên với tên của dữ liệu thành viên và sử dụng con trỏ this trong hàm xây dựng. Như ở ví dụ trên nếu chúng ta không đặt tên tham số trùng với tên dữ liệu thành viên mà sử dụng các chữ cái như m, t, g... thì tên đó không có ý nghĩa gì hết.

Vậy mình sẽ kết thúc bài học này ở đây. Bài tiếp theo chúng ta sẽ cùng tìm hiểu về từ khóa static trong C++. Các bạn nhớ theo dõi nhé.

Khóa học nên xem

Nguồn: freetuts.net