Giao diện
👆 The this Pointer — Self-Reference
this là con trỏ ẩn (implicit) trong mọi non-static member function, trỏ đến object đang gọi function. this là gì?
cpp
#include <iostream>
class Box {
private:
double width_;
public:
Box(double width) : width_(width) {}
void showThis() {
std::cout << "Address of this object: " << this << std::endl;
std::cout << "this->width_ = " << this->width_ << std::endl;
}
double getWidth() {
return this->width_; // Tường minh, nhưng không bắt buộc
// return width_; // Cũng OK — this-> là implicit
}
};
int main() {
Box b1(10);
Box b2(20);
std::cout << "b1 address: " << &b1 << std::endl;
b1.showThis(); // Matches &b1
std::cout << "\nb2 address: " << &b2 << std::endl;
b2.showThis(); // Matches &b2
return 0;
}Output:
b1 address: 0x7ffd12345678
Address of this object: 0x7ffd12345678
this->width_ = 10
b2 address: 0x7ffd12345690
Address of this object: 0x7ffd12345690
this->width_ = 20Khi nào CẦN dùng this?
1. Phân biệt member và parameter cùng tên
cpp
class Person {
private:
std::string name;
int age;
public:
// Parameter có cùng tên với member
Person(std::string name, int age) {
this->name = name; // ✅ this->name = member, name = param
this->age = age;
}
// Hoặc dùng naming convention để tránh:
// Person(std::string name, int age) : name_(name), age_(age) {}
};2. Return object hiện tại (Method Chaining)
cpp
#include <iostream>
class Calculator {
private:
double result_ = 0;
public:
// Return reference tới *this cho chaining
Calculator& add(double x) {
result_ += x;
return *this;
}
Calculator& multiply(double x) {
result_ *= x;
return *this;
}
Calculator& subtract(double x) {
result_ -= x;
return *this;
}
double getResult() const {
return result_;
}
};
int main() {
Calculator calc;
// Method chaining — fluent interface!
double result = calc.add(10)
.multiply(2)
.subtract(5)
.getResult();
std::cout << "Result: " << result << std::endl; // (10 * 2) - 5 = 15
return 0;
}3. Truyền object hiện tại cho function khác
cpp
#include <iostream>
class Node; // Forward declaration
void processNode(Node* node);
class Node {
private:
int value_;
public:
explicit Node(int val) : value_(val) {}
void doSomething() {
// Truyền chính mình cho function khác
processNode(this);
}
int getValue() const { return value_; }
};
void processNode(Node* node) {
std::cout << "Processing node with value: " << node->getValue() << std::endl;
}
int main() {
Node n(42);
n.doSomething(); // Processing node with value: 42
return 0;
}4. So sánh với object khác
cpp
class MyClass {
public:
bool isSameObject(const MyClass& other) const {
return this == &other; // So sánh địa chỉ
}
MyClass& operator=(const MyClass& other) {
if (this != &other) { // ✅ Check self-assignment!
// Copy data...
}
return *this;
}
};this trong const Methods
cpp
class Counter {
private:
int count_ = 0;
public:
// Non-const method: this có type Counter*
void increment() {
++count_;
// this có type: Counter* const
// (pointer không đổi, object có thể đổi)
}
// const method: this có type const Counter*
int getCount() const {
// this có type: const Counter* const
// (không thể modify object qua this)
// count_ = 10; // ❌ Error: this is const!
return count_;
}
};this KHÔNG tồn tại trong static methods
cpp
class Utility {
private:
static int instanceCount_;
int id_;
public:
Utility() : id_(++instanceCount_) {}
// Static method — không có this!
static int getInstanceCount() {
// return this->instanceCount_; // ❌ Error: no 'this' in static
return instanceCount_; // ✅ Access static member trực tiếp
}
int getId() const { // Non-static — có this
return this->id_;
}
};
int Utility::instanceCount_ = 0;📚 Tổng kết
| Concept | Key Takeaway |
|---|---|
this | Pointer to current object |
| Type | ClassName* const (non-const) hoặc const ClassName* const |
| Use case 1 | Phân biệt member vs parameter cùng tên |
| Use case 2 | Return *this cho method chaining |
| Use case 3 | Truyền object cho function khác |
| Use case 4 | Check self-assignment |
| Static methods | Không có this |
➡️ Tiếp theo
Tiếp theo: Member Initialization — Modern initialization list.