C++学习笔记-this指针

this是一个指向当前对象的指针,它在每个非静态成员函数中都隐式可用。理解this指针对于解决命名冲突、实现链式调用和理解C++对象模型都很重要。

this指针的基本概念

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>

class Entity
{
public:
    int x, y;
    
    Entity(int x, int y)
    {
        // this是指向当前对象的指针
        Entity* e = this;
        
        // 使用this解决参数名与成员变量名冲突
        this->x = x;
        this->y = y;
        
        // 等价写法(编译器会自动添加this->)
        // this->x = x;
        // this->y = y;
    }
    
    void PrintAddress()
    {
        std::cout << "Object address: " << this << std::endl;
        std::cout << "x address: " << &(this->x) << std::endl;
        std::cout << "y address: " << &(this->y) << std::endl;
    }
};

int main()
{
    Entity e1(10, 20);
    Entity e2(30, 40);
    
    e1.PrintAddress();
    e2.PrintAddress();
    // 每个对象的this指针都指向不同的地址
}

解决命名冲突

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Player
{
private:
    std::string name;
    int health;
    int level;
    
public:
    // 不使用this的写法(需要不同的参数名)
    Player(const std::string& playerName, int playerHealth, int playerLevel)
        : name(playerName), health(playerHealth), level(playerLevel) {}
    
    // 使用this的写法(可以使用相同的参数名)
    void SetStats(const std::string& name, int health, int level)
    {
        this->name = name;      // 明确指定是成员变量
        this->health = health;
        this->level = level;
    }
    
    // 不使用this的错误示例
    void BadSetName(const std::string& name)
    {
        name = name;  // 错误:参数赋值给自己,成员变量没有改变
    }
    
    // 正确的写法
    void SetName(const std::string& name)
    {
        this->name = name;  // 正确:成员变量被赋值
    }
    
    void PrintInfo() const
    {
        std::cout << "Name: " << name << ", Health: " << health 
                  << ", Level: " << level << std::endl;
    }
};

链式调用(Method Chaining)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Calculator
{
private:
    double m_Value;
    
public:
    Calculator(double value = 0) : m_Value(value) {}
    
    // 返回*this实现链式调用
    Calculator& Add(double value)
    {
        m_Value += value;
        return *this;  // 返回当前对象的引用
    }
    
    Calculator& Subtract(double value)
    {
        m_Value -= value;
        return *this;
    }
    
    Calculator& Multiply(double value)
    {
        m_Value *= value;
        return *this;
    }
    
    Calculator& Divide(double value)
    {
        if (value != 0)
            m_Value /= value;
        return *this;
    }
    
    double GetResult() const { return m_Value; }
    
    void Print() const
    {
        std::cout << "Result: " << m_Value << std::endl;
    }
};

int main()
{
    Calculator calc(10);
    
    // 链式调用
    calc.Add(5).Multiply(2).Subtract(10).Divide(2);
    calc.Print();  // 输出: Result: 10
    
    // 等价于:
    // calc.Add(5);
    // calc.Multiply(2);
    // calc.Subtract(10);
    // calc.Divide(2);
}

自赋值检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class MyString
{
private:
    char* m_Data;
    size_t m_Size;
    
public:
    MyString(const char* str)
    {
        m_Size = strlen(str);
        m_Data = new char[m_Size + 1];
        strcpy(m_Data, str);
    }
    
    ~MyString()
    {
        delete[] m_Data;
    }
    
    // 拷贝赋值运算符
    MyString& operator=(const MyString& other)
    {
        // 自赋值检查
        if (this == &other)
        {
            return *this;  // 如果是自己赋值给自己,直接返回
        }
        
        // 释放原有内存
        delete[] m_Data;
        
        // 分配新内存并拷贝
        m_Size = other.m_Size;
        m_Data = new char[m_Size + 1];
        strcpy(m_Data, other.m_Data);
        
        return *this;
    }
    
    const char* GetData() const { return m_Data; }
};

int main()
{
    MyString str1("Hello");
    MyString str2("World");
    
    str2 = str1;     // 正常赋值
    str1 = str1;     // 自赋值,会被检测到并直接返回
}

this在不同上下文中的使用

1. 成员函数中的this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Example
{
private:
    int m_Value;
    
public:
    Example(int value) : m_Value(value) {}
    
    void MemberFunction()
    {
        // 在成员函数中,this总是可用的
        std::cout << "this = " << this << std::endl;
        std::cout << "m_Value = " << this->m_Value << std::endl;
        
        // 以下两种写法等价
        m_Value = 100;        // 编译器自动添加this->
        this->m_Value = 100;  // 显式使用this
    }
    
    // 静态成员函数中没有this指针
    static void StaticFunction()
    {
        // std::cout << this << std::endl;  // 错误:静态函数没有this
    }
};

2. const成员函数中的this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class ConstExample
{
private:
    int m_Value;
    
public:
    ConstExample(int value) : m_Value(value) {}
    
    void NonConstFunction()
    {
        // 非const函数中,this的类型是 ConstExample*
        ConstExample* ptr = this;  // 正确
    }
    
    void ConstFunction() const
    {
        // const函数中,this的类型是 const ConstExample*
        const ConstExample* ptr = this;  // 正确
        // ConstExample* ptr2 = this;    // 错误:不能去掉const
        
        // 不能通过this修改成员变量
        // this->m_Value = 100;  // 错误:const函数不能修改成员
    }
};

实际应用示例

1. 建造者模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class HttpRequest
{
private:
    std::string m_Url;
    std::string m_Method;
    std::map<std::string, std::string> m_Headers;
    std::string m_Body;
    
public:
    HttpRequest& SetUrl(const std::string& url)
    {
        m_Url = url;
        return *this;
    }
    
    HttpRequest& SetMethod(const std::string& method)
    {
        m_Method = method;
        return *this;
    }
    
    HttpRequest& AddHeader(const std::string& key, const std::string& value)
    {
        m_Headers[key] = value;
        return *this;
    }
    
    HttpRequest& SetBody(const std::string& body)
    {
        m_Body = body;
        return *this;
    }
    
    void Send()
    {
        std::cout << "Sending " << m_Method << " request to " << m_Url << std::endl;
        // 实际发送逻辑...
    }
};

int main()
{
    HttpRequest request;
    
    // 流畅的API设计
    request.SetUrl("https://api.example.com/users")
           .SetMethod("POST")
           .AddHeader("Content-Type", "application/json")
           .AddHeader("Authorization", "Bearer token123")
           .SetBody("{\"name\":\"John\",\"age\":30}")
           .Send();
}

2. 观察者模式中的this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Observer
{
public:
    virtual void OnNotify() = 0;
};

class Subject
{
private:
    std::vector<Observer*> m_Observers;
    
public:
    void AddObserver(Observer* observer)
    {
        m_Observers.push_back(observer);
    }
    
    void RemoveObserver(Observer* observer)
    {
        auto it = std::find(m_Observers.begin(), m_Observers.end(), observer);
        if (it != m_Observers.end())
            m_Observers.erase(it);
    }
    
    void NotifyAll()
    {
        for (Observer* observer : m_Observers)
            observer->OnNotify();
    }
};

class ConcreteObserver : public Observer
{
private:
    Subject* m_Subject;
    
public:
    ConcreteObserver(Subject* subject) : m_Subject(subject)
    {
        m_Subject->AddObserver(this);  // 将自己注册为观察者
    }
    
    ~ConcreteObserver()
    {
        m_Subject->RemoveObserver(this);  // 移除自己
    }
    
    void OnNotify() override
    {
        std::cout << "Observer " << this << " notified!" << std::endl;
    }
};

总结

  1. this是指向当前对象的指针,在每个非静态成员函数中都可用
  2. 解决命名冲突:当参数名与成员变量名相同时,使用this->明确指定成员变量
  3. 链式调用:通过返回*this实现方法链式调用,提高API的流畅性
  4. 自赋值检查:在赋值运算符中使用this == &other检查自赋值
  5. 类型特性:在const成员函数中,this的类型是const T*;在非const成员函数中是T*
updatedupdated2025-09-202025-09-20