C++学习笔记-运算符重载

运算符重载允许我们为自定义类型定义运算符的行为,使得自定义类型可以像内置类型一样使用运算符,提高代码的可读性和直观性。

基本的运算符重载

 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
#include <iostream>

struct Vector2
{
    float x, y;

    Vector2(float x, float y)
        : x(x), y(y) {}

    // 传统的方法
    Vector2 Add(const Vector2& other) const
    {
        return Vector2(x + other.x, y + other.y);
    }

    // 重载 + 运算符
    Vector2 operator+(const Vector2& other) const
    {
        return Add(other);
    }

    // 重载 == 运算符
    bool operator==(const Vector2& other) const
    {
        return x == other.x && y == other.y;
    }
    
    // 重载 != 运算符
    bool operator!=(const Vector2& other) const
    {
        return !(*this == other);
    }
};

int main()
{
    Vector2 position(4.0f, 4.0f);
    Vector2 speed(0.5f, 1.5f);
    
    // 传统方法
    Vector2 result1 = position.Add(speed);
    
    // 使用重载的运算符
    Vector2 result2 = position + speed;
    
    // 比较运算符
    Vector2 position2(4.0f, 4.0f);
    if (position == position2)
        std::cout << "Positions are equal" << std::endl;
}

输出流运算符重载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 重载 << 运算符(必须作为全局函数)
std::ostream& operator<<(std::ostream& stream, const Vector2& vector)
{
    stream << vector.x << ", " << vector.y;
    return stream;
}

int main()
{
    Vector2 position(4.0f, 4.0f);
    std::cout << position << std::endl;  // 输出: 4, 4
}

算术运算符重载

 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
struct Vector2
{
    float x, y;

    Vector2(float x, float y) : x(x), y(y) {}

    // 加法
    Vector2 operator+(const Vector2& other) const
    {
        return Vector2(x + other.x, y + other.y);
    }

    // 减法
    Vector2 operator-(const Vector2& other) const
    {
        return Vector2(x - other.x, y - other.y);
    }

    // 乘法(标量)
    Vector2 operator*(float scalar) const
    {
        return Vector2(x * scalar, y * scalar);
    }

    // 除法(标量)
    Vector2 operator/(float scalar) const
    {
        return Vector2(x / scalar, y / scalar);
    }

    // 负号
    Vector2 operator-() const
    {
        return Vector2(-x, -y);
    }
};

// 标量乘法(左操作数是标量)
Vector2 operator*(float scalar, const Vector2& vector)
{
    return vector * scalar;
}

int main()
{
    Vector2 v1(2.0f, 3.0f);
    Vector2 v2(1.0f, 1.0f);
    
    Vector2 sum = v1 + v2;        // (3, 4)
    Vector2 diff = v1 - v2;       // (1, 2)
    Vector2 scaled = v1 * 2.0f;   // (4, 6)
    Vector2 scaled2 = 2.0f * v1;  // (4, 6)
    Vector2 divided = v1 / 2.0f;  // (1, 1.5)
    Vector2 negated = -v1;        // (-2, -3)
}

赋值运算符重载

 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
struct Vector2
{
    float x, y;

    Vector2(float x, float y) : x(x), y(y) {}

    // 拷贝赋值运算符
    Vector2& operator=(const Vector2& other)
    {
        if (this != &other)  // 自赋值检查
        {
            x = other.x;
            y = other.y;
        }
        return *this;
    }

    // 复合赋值运算符
    Vector2& operator+=(const Vector2& other)
    {
        x += other.x;
        y += other.y;
        return *this;
    }

    Vector2& operator-=(const Vector2& other)
    {
        x -= other.x;
        y -= other.y;
        return *this;
    }

    Vector2& operator*=(float scalar)
    {
        x *= scalar;
        y *= scalar;
        return *this;
    }
};

int main()
{
    Vector2 v1(2.0f, 3.0f);
    Vector2 v2(1.0f, 1.0f);
    
    v1 += v2;      // v1 = (3, 4)
    v1 -= v2;      // v1 = (2, 3)
    v1 *= 2.0f;    // v1 = (4, 6)
}

下标运算符重载

 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
class Array
{
private:
    int* m_Data;
    size_t m_Size;
public:
    Array(size_t size) : m_Size(size)
    {
        m_Data = new int[size];
        for (size_t i = 0; i < size; ++i)
            m_Data[i] = 0;
    }

    ~Array()
    {
        delete[] m_Data;
    }

    // 下标运算符(非const版本)
    int& operator[](size_t index)
    {
        return m_Data[index];
    }

    // 下标运算符(const版本)
    const int& operator[](size_t index) const
    {
        return m_Data[index];
    }

    size_t Size() const { return m_Size; }
};

int main()
{
    Array arr(5);
    
    arr[0] = 10;
    arr[1] = 20;
    
    std::cout << arr[0] << std::endl;  // 输出: 10
    
    const Array& constArr = arr;
    std::cout << constArr[1] << std::endl;  // 调用const版本
}

函数调用运算符重载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Multiplier
{
private:
    float m_Factor;
public:
    Multiplier(float factor) : m_Factor(factor) {}

    // 函数调用运算符
    float operator()(float value) const
    {
        return value * m_Factor;
    }
};

int main()
{
    Multiplier doubler(2.0f);
    
    float result = doubler(5.0f);  // 等价于 doubler.operator()(5.0f)
    std::cout << result << std::endl;  // 输出: 10
}

递增递减运算符重载

 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
class Counter
{
private:
    int m_Value;
public:
    Counter(int value = 0) : m_Value(value) {}

    // 前置递增
    Counter& operator++()
    {
        ++m_Value;
        return *this;
    }

    // 后置递增(注意int参数用于区分)
    Counter operator++(int)
    {
        Counter temp = *this;
        ++m_Value;
        return temp;
    }

    // 前置递减
    Counter& operator--()
    {
        --m_Value;
        return *this;
    }

    // 后置递减
    Counter operator--(int)
    {
        Counter temp = *this;
        --m_Value;
        return temp;
    }

    int GetValue() const { return m_Value; }
};

int main()
{
    Counter c(5);
    
    ++c;                    // 前置递增,c = 6
    Counter c2 = c++;       // 后置递增,c2 = 6, c = 7
    --c;                    // 前置递减,c = 6
    Counter c3 = c--;       // 后置递减,c3 = 6, c = 5
}

智能指针的运算符重载

 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
template<typename T>
class SmartPtr
{
private:
    T* m_Ptr;
public:
    explicit SmartPtr(T* ptr) : m_Ptr(ptr) {}
    
    ~SmartPtr() { delete m_Ptr; }

    // 解引用运算符
    T& operator*() const
    {
        return *m_Ptr;
    }

    // 成员访问运算符
    T* operator->() const
    {
        return m_Ptr;
    }

    // 转换为bool
    explicit operator bool() const
    {
        return m_Ptr != nullptr;
    }
};

class TestClass
{
public:
    void DoSomething() { std::cout << "Doing something..." << std::endl; }
    int value = 42;
};

int main()
{
    SmartPtr<TestClass> ptr(new TestClass());
    
    if (ptr)  // 使用operator bool
    {
        (*ptr).DoSomething();    // 使用operator*
        ptr->DoSomething();      // 使用operator->
        std::cout << ptr->value << std::endl;
    }
}

注意事项和最佳实践

1. 不能重载的运算符

1
2
3
4
5
6
// 以下运算符不能重载:
// .  (成员访问)
// :: (作用域解析)
// ?: (三元运算符)
// sizeof
// typeid

2. 运算符重载的原则

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class GoodExample
{
public:
    // 保持运算符的直观含义
    GoodExample operator+(const GoodExample& other) const;  // 加法应该返回新对象
    GoodExample& operator+=(const GoodExample& other);      // 复合赋值应该修改当前对象
    
    // 对称运算符应该作为非成员函数
    friend GoodExample operator*(const GoodExample& lhs, const GoodExample& rhs);
    
    // 输入输出运算符必须是非成员函数
    friend std::ostream& operator<<(std::ostream& os, const GoodExample& obj);
};

总结

  1. 运算符重载本质上就是函数重载,让自定义类型可以使用运算符
  2. 保持直观性:重载的运算符应该保持其原有的语义
  3. 返回类型:算术运算符返回新对象,赋值运算符返回引用
  4. 成员vs非成员:一般规则是如果运算符修改对象状态,定义为成员函数;否则定义为非成员函数
  5. 特殊运算符:某些运算符(如<<、>>)必须定义为非成员函数
updatedupdated2025-09-202025-09-20