
Giảng viên Creyt xin chào các Gen Z mê code! Hôm nay, chúng ta sẽ "bóc tách" một từ khóa nghe có vẻ đơn giản nhưng lại là "trùm cuối" trong thế giới C++ hướng đối tượng: this.
Tưởng tượng thế này, bạn là một "TikToker triệu view" tên Creyt. Mỗi khi bạn quay video và nói "tôi" hay "mình" đang làm gì đó, ai cũng hiểu bạn đang nói về CHÍNH BẠN, chứ không phải cô bé trợ lý đang cầm điện thoại quay hộ. Trong C++, mỗi khi một đối tượng (object) của một class cần "tự nhận dạng" chính nó, nó sẽ dùng this.
this (đọc là "đít" hoặc "thít", tùy bạn thích) thực chất là một con trỏ (pointer) đặc biệt. Nó không phải là một biến mà bạn khai báo, mà là một "món quà" tự động được tặng cho MỌI phương thức không tĩnh (non-static member function) bên trong một class. Nhiệm vụ cao cả của nó? Trỏ thẳng vào cái đối tượng (instance) mà phương thức đó đang được gọi. Đơn giản là vậy đó: nó là địa chỉ của "ngôi nhà" mà bạn đang ở.
Dùng để làm gì á? Nó có vài "siêu năng lực" sau:
- Phân biệt "Tên giống tên": Khi bạn có một biến thành viên (member variable) và một tham số (parameter) của phương thức có tên giống hệt nhau,
thissẽ giúp bạn chỉ rõ: "À, cái này là biến của TÔI đây này!" - Tự mình quay về nhà: Muốn một phương thức trả về chính đối tượng hiện tại để bạn có thể gọi thêm các phương thức khác một cách "liền mạch" (kiểu như
object.method1().method2().method3())? Dùngreturn *this; - Tự mình đi chơi: Khi bạn cần truyền chính đối tượng hiện tại làm tham số cho một hàm hay phương thức khác,
thischính là thứ bạn cần.
Code Ví Dụ Minh Hoạ
Để dễ hình dung, hãy cùng xây dựng một class NguoiDungTikTok nhé:
#include <iostream>
#include <string>
class NguoiDungTikTok {
private:
std::string tenNguoiDung;
int soFollower;
public:
// Constructor (Hàm tạo)
NguoiDungTikTok(std::string tenNguoiDung, int soFollower) {
// Đây là ví dụ kinh điển nhất của 'this'
// tenNguoiDung (bên trái dấu =) là biến thành viên của class
// tenNguoiDung (bên phải dấu =) là tham số truyền vào hàm tạo
this->tenNguoiDung = tenNguoiDung;
this->soFollower = soFollower; // Tương tự
std::cout << "Xin chào, mình là " << this->tenNguoiDung << "!" << std::endl;
}
// Phương thức tăng follower
NguoiDungTikTok& tangFollower(int luongTang) {
this->soFollower += luongTang;
std::cout << this->tenNguoiDung << " vừa tăng " << luongTang << " follower. Tổng: " << this->soFollower << std::endl;
return *this; // Trả về chính đối tượng hiện tại để chaining
}
// Phương thức hiển thị thông tin
void hienThiThongTin() const {
std::cout << "--- Thông tin người dùng ---" << std::endl;
std::cout << "Tên: " << this->tenNguoiDung << std::endl; // Dùng this cho rõ ràng, dù không bắt buộc
std::cout << "Follower: " << soFollower << std::endl; // Không dùng this cũng được nếu không trùng tên
}
// Phương thức kiểm tra tài khoản (ví dụ truyền 'this' đi)
void kiemTraTaiKhoan(NguoiDungTikTok* taiKhoanCanKiemTra) {
if (this == taiKhoanCanKiemTra) { // So sánh địa chỉ của hai đối tượng
std::cout << this->tenNguoiDung << " tự kiểm tra chính mình." << std::endl;
} else {
std::cout << this->tenNguoiDung << " đang kiểm tra tài khoản khác." << std::endl;
}
}
};
int main() {
NguoiDungTikTok creyt("CreytCoder", 10000);
creyt.hienThiThongTin();
// Ví dụ về chaining (chuỗi phương thức)
std::cout << "\n--- Kịch bản tăng follower ---" << std::endl;
creyt.tangFollower(5000).tangFollower(2000).hienThiThongTin();
NguoiDungTikTok coGiaoThao("CoGiaoThao", 20000);
std::cout << "\n--- Kịch bản kiểm tra tài khoản ---" << std::endl;
creyt.kiemTraTaiKhoan(&creyt); // Truyền chính đối tượng creyt
creyt.kiemTraTaiKhoan(&coGiaoThao); // Truyền đối tượng coGiaoThao
return 0;
}
Mẹo Ghi Nhớ & Best Practices
Giảng đường Harvard thường dạy "nguyên tắc vàng" đấy các bạn! Với this, hãy nhớ:
thislà "Tôi" của Object: Cứ nghĩ đếnthis, là nghĩ đến việc đối tượng đang nói "chính tôi đây này!"- Khi nào NÊN dùng
this->rõ ràng:- Tránh nhầm lẫn: Khi tên biến thành viên và tham số hàm giống nhau (như trong hàm tạo ở ví dụ trên). Đây là lúc
thistỏa sáng nhất. - Fluent Interface (Method Chaining): Khi bạn muốn các phương thức của mình có thể gọi nối tiếp nhau kiểu
.method1().method2(), hãyreturn *this;(trả về tham chiếu của đối tượng hiện tại). - Truyền chính nó: Khi bạn cần truyền đối tượng hiện tại vào một hàm khác.
- Tránh nhầm lẫn: Khi tên biến thành viên và tham số hàm giống nhau (như trong hàm tạo ở ví dụ trên). Đây là lúc
- Khi nào KHÔNG NHẤT THIẾT dùng
this->:- Nếu không có sự trùng tên giữa biến thành viên và biến cục bộ/tham số, việc dùng
this->là hoàn toàn tùy chọn. Trình biên dịch hiểu cả hai. Tuy nhiên, một số team code lại khuyến khích dùngthis->cho tất cả biến thành viên để tăng tính rõ ràng. Quan trọng là thống nhất trong team!
- Nếu không có sự trùng tên giữa biến thành viên và biến cục bộ/tham số, việc dùng
thisluôn là con trỏ: Vì nó là con trỏ, nên để truy cập các thành viên của đối tượng mà nó trỏ tới, bạn phải dùng toán tử->(hoặc(*this).).

Góc Nhìn Học Thuật Sâu (Nhưng Dễ Hiểu)
Từ góc độ của Đại học Harvard (mà Creyt từng "ngồi ké" nghe giảng), this không chỉ là một tiện ích, nó là nền tảng của lập trình hướng đối tượng trong C++.
- Sự Tồn Tại Ngầm:
thiskhông phải là một biến mà bạn định nghĩa. Nó là một tham số ẩn (implicit parameter) được truyền vào mọi phương thức không tĩnh của class. Khi bạn gọicreyt.tangFollower(5000), thực chất nó tương đương với một lời gọi hàm kiểutangFollower(&creyt, 5000)nếutangFollowerlà một hàm toàn cục vàthisđược truyền rõ ràng. - Const Correctness: Nếu phương thức của bạn là
const(không thay đổi trạng thái của đối tượng), thìthistrong phương thức đó sẽ có kiểuconst NguoiDungTikTok* const. Điều này đảm bảo bạn không thể dùngthisđể thay đổi bất kỳ biến thành viên nào trong phương thứcconst, giữ cho code của bạn an toàn và dễ bảo trì hơn. Đây là một điểm cực kỳ quan trọng trong C++ hiện đại. - Không Dùng Cho Static Methods: Các phương thức tĩnh (static methods) không thuộc về bất kỳ đối tượng cụ thể nào, chúng thuộc về class. Vì vậy, chúng không có "ngôi nhà" để
thistrỏ vào. Do đó, bạn không thể sử dụngthistrong các phương thức tĩnh.
Ứng Dụng Thực Tế (Không chỉ TikTok!)
this không chỉ là lý thuyết suông, nó hiện diện khắp nơi trong các ứng dụng "khủng" mà bạn dùng hàng ngày:
- Thư viện đồ họa/UI (Qt, wxWidgets, MFC): Khi bạn tạo một nút bấm, một cửa sổ, các sự kiện (event) thường được xử lý bởi các phương thức của chính đối tượng đó.
thisđược dùng để tham chiếu đến chính widget đang xử lý sự kiện.- Ví dụ: Trong Qt, khi bạn thiết kế một giao diện, các đối tượng như
QPushButton,QLabelđều là các instance của class. Các hàm xử lý tín hiệu (slot) của chúng thường dùngthisđể truy cập các thuộc tính hoặc gọi các phương thức khác của chính đối tượng đó.
- Ví dụ: Trong Qt, khi bạn thiết kế một giao diện, các đối tượng như
- Game Engines (Unreal Engine, Unity - qua C#): Trong game, mọi thứ từ nhân vật, vật phẩm, môi trường đều là các đối tượng. Khi nhân vật nhặt một vật phẩm, phương thức
nhanVat.nhatVatPham(vatPham)sẽ dùngthisđể chỉ nhân vật đang thực hiện hành động. - Framework PHP (Laravel, Symfony) / Java (Spring) / C# (.NET): Mặc dù cú pháp có thể khác (
$thistrong PHP,thistrong Java/C#), nhưng nguyên lý là y hệt. Các framework này tận dụngthistriệt để để xây dựng các API linh hoạt, cho phép bạn gọi các phương thức nối tiếp nhau (method chaining) để cấu hình đối tượng hoặc truy vấn dữ liệu một cách "mượt mà".- Ví dụ: Trong một framework ORM (Object-Relational Mapping), bạn có thể viết:
user->where('age', '>', 18)->orderBy('name')->get();– mỗi phương thứcwhere,orderByđều trả về$this(hoặcthis) để bạn có thể tiếp tục gọi phương thức khác.
- Ví dụ: Trong một framework ORM (Object-Relational Mapping), bạn có thể viết:
Thử Nghiệm & Hướng Dẫn Nên Dùng Cho Case Nào
Thử nghiệm đã từng:
Hồi mới học, Creyt cũng từng bị "lú" với this. Có lần, cố gắng dùng this trong một hàm static và bị compiler "phang" lỗi đỏ lòm. Hay có lần, quên mất * khi return *this; cho method chaining, kết quả là chương trình trả về địa chỉ chứ không phải đối tượng, và mọi thứ "bay màu" ngay lập tức. Những lỗi này giúp mình hiểu sâu hơn bản chất của this là một con trỏ.
Hướng dẫn nên dùng cho case nào:
- Gỡ rối khi trùng tên (Disambiguation): Đây là "case" bắt buộc phải dùng
this. Nếu bạn có tham số constructor/hàm trùng tên với biến thành viên,this->bien = bien;là cách duy nhất để compiler biết bạn đang gán giá trị của tham sốbiencho biến thành viênthis->bien. - Tạo Fluent Interface (Method Chaining): Khi bạn muốn xây dựng các API "ngầu lòi" như ví dụ
creyt.tangFollower(5000).tangFollower(2000).hienThiThongTin();, hãy trả về*this(tham chiếu của đối tượng hiện tại) từ các phương thức không phảivoid. - Truyền bản thân đối tượng: Nếu một hàm bên ngoài cần một con trỏ hoặc tham chiếu đến chính đối tượng hiện tại để làm việc (ví dụ: đăng ký đối tượng vào một hệ thống quản lý, hoặc kiểm tra so sánh như ví dụ
kiemTraTaiKhoan), bạn có thể truyềnthis(cho con trỏ) hoặc*this(cho tham chiếu).
Nhớ nhé các Gen Z, this không chỉ là một từ khóa, nó là linh hồn của mỗi đối tượng trong C++, giúp chúng "tự ý thức" và tương tác một cách mạnh mẽ. Hiểu rõ this là bạn đã nắm được một trong những "vũ khí" quan trọng nhất để làm chủ OOP rồi đấy! Keep coding!
Thuộc Series: C++
Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!