【C++重载操作符与转换】算数操作符和关系操作符

目录

一、操作符重载的核心价值

1.1 为什么要重载算术与关系操作符

1.2 操作符重载基本原则

1.3 操作符重载的分类

二、算数操作符重载

2.1 基本概念

2.2 重载加法操作符 +

2.3 重载减法、乘法和除法操作符

2.4 重载复合赋值操作符

三、关系操作符重载

3.1 基本概念

3.2 重载相等操作符 ==

3.3 重载其他关系操作符

四、操作符重载的注意事项

4.1 操作符重载的限制

4.2 成员函数和非成员函数重载

4.3 保持操作符的语义一致性

五、总结

六、代码示例总结

6.1 复数类 Complex 完整代码 

6.2 点类 Point 完整代码


在C++中,操作符重载是一项强大的特性,它允许开发者为自定义类型(如类或结构体)重新定义内置操作符(如+-==等)的行为。这种机制使得自定义类型能够像内置类型一样,通过操作符进行直观的操作。本文将深入探讨算数操作符和关系操作符的重载,结合代码示例和关键知识点,全面掌握这一重要特性。

一、操作符重载的核心价值

1.1 为什么要重载算术与关系操作符

在面向对象编程中,操作符重载赋予自定义类型与内置类型一致的操作体验。对于数学相关类型(如复数、矩阵、几何向量),合理的操作符重载可以:

  • 提升代码可读性

  • 增强类型安全性

  • 实现数学表达式自然表达

// 未重载操作符
Matrix result = matrix1.add(matrix2.multiply(matrix3));

// 重载操作符后
Matrix result = matrix1 + matrix2 * matrix3;

1.2 操作符重载基本原则

原则说明示例验证
语义一致性操作符行为符合直觉a + b 应执行加法而非其他操作
完备性相关操作符组应完整重载重载==必须同时重载!=
效率优化避免不必要的临时对象创建使用复合赋值操作符优化运算

1.3 操作符重载的分类

分类操作符示例设计建议
算术操作符+-*/通常定义为非成员函数,不修改操作数状态,返回新对象。
关系操作符==!=<><=>=通常定义为非成员函数,用于比较对象,支持STL容器(如std::sort)的排序需求。
赋值操作符=必须定义为成员函数,返回*this的引用,支持链式赋值。
复合赋值操作符+=-=*=/=若类支持算术操作符,建议同时定义,提升代码可读性。
自增/自减操作符++--通常定义为成员函数,区分前缀(返回引用)和后缀(返回旧值)形式。

二、算数操作符重载

2.1 基本概念

算数操作符包括 +-*/% 等,用于执行基本的数学运算。在 C++ 中,我们可以为自定义类重载这些操作符,使得它们能够对类对象进行相应的运算。

2.2 重载加法操作符 +

下面以一个简单的 Complex 类(复数类)为例,展示如何重载加法操作符 +。 

#include <iostream>

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // 重载加法操作符
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }

    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
};

int main() {
    Complex c1(1, 2);
    Complex c2(3, 4);
    Complex c3 = c1 + c2;

    std::cout << "c1: ";
    c1.display();
    std::cout << "c2: ";
    c2.display();
    std::cout << "c1 + c2: ";
    c3.display();

    return 0;
}

 

定义了一个 Complex 类,并重载了加法操作符 +。重载函数 operator+ 接受一个 const Complex& 类型的参数,表示另一个复数对象,返回一个新的 Complex 对象,其实部和虚部分别是两个复数对象实部和虚部的和。

2.3 重载减法、乘法和除法操作符

类似地,我们可以重载减法、乘法和除法操作符。以下是完整的 Complex 类代码,包含了所有这些操作符的重载: 

#include <iostream>

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // 重载加法操作符
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }

    // 重载减法操作符
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }

    // 重载乘法操作符
    Complex operator*(const Complex& other) const {
        double newReal = real * other.real - imag * other.imag;
        double newImag = real * other.imag + imag * other.real;
        return Complex(newReal, newImag);
    }

    // 重载除法操作符
    Complex operator/(const Complex& other) const {
        double denominator = other.real * other.real + other.imag * other.imag;
        double newReal = (real * other.real + imag * other.imag) / denominator;
        double newImag = (imag * other.real - real * other.imag) / denominator;
        return Complex(newReal, newImag);
    }

    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
};

int main() {
    Complex c1(1, 2);
    Complex c2(3, 4);

    Complex sum = c1 + c2;
    Complex diff = c1 - c2;
    Complex prod = c1 * c2;
    Complex quot = c1 / c2;

    std::cout << "c1: ";
    c1.display();
    std::cout << "c2: ";
    c2.display();

    std::cout << "c1 + c2: ";
    sum.display();
    std::cout << "c1 - c2: ";
    diff.display();
    std::cout << "c1 * c2: ";
    prod.display();
    std::cout << "c1 / c2: ";
    quot.display();

    return 0;
}

 

2.4 重载复合赋值操作符

复合赋值操作符如 +=-=*=/= 等也可以被重载。以下是 Complex 类中重载 += 操作符的示例: 

#include <iostream>

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // 重载 += 操作符
    Complex& operator+=(const Complex& other) {
        real += other.real;
        imag += other.imag;
        return *this;
    }

    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
};

int main() {
    Complex c1(1, 2);
    Complex c2(3, 4);

    c1 += c2;

    std::cout << "c1 after c1 += c2: ";
    c1.display();

    return 0;
}

 

operator+= 函数返回 *this 的引用,这样可以支持链式调用,例如 c1 += c2 += c3;

三、关系操作符重载

3.1 基本概念

关系操作符包括 ==!=<><=>= 等,用于比较两个对象的大小或相等性。通过重载这些操作符,我们可以自定义类对象之间的比较规则。

3.2 重载相等操作符 ==

以下是一个 Point 类,用于表示二维平面上的点,并重载了相等操作符 ==: 

#include <iostream>

class Point {
private:
    int x;
    int y;
public:
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}

    // 重载相等操作符
    bool operator==(const Point& other) const {
        return (x == other.x) && (y == other.y);
    }
};

int main() {
    Point p1(1, 2);
    Point p2(1, 2);
    Point p3(3, 4);

    if (p1 == p2) {
        std::cout << "p1 and p2 are equal." << std::endl;
    } else {
        std::cout << "p1 and p2 are not equal." << std::endl;
    }

    if (p1 == p3) {
        std::cout << "p1 and p3 are equal." << std::endl;
    } else {
        std::cout << "p1 and p3 are not equal." << std::endl;
    }

    return 0;
}

 

operator== 函数接受一个 const Point& 类型的参数,表示另一个点对象,返回一个布尔值,表示两个点是否相等。

3.3 重载其他关系操作符

类似地,我们可以重载其他关系操作符。以下是 Point 类中重载 < 操作符的示例:

#include <iostream>

class Point {
private:
    int x;
    int y;
public:
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}

    // 重载 < 操作符
    bool operator<(const Point& other) const {
        if (x < other.x) {
            return true;
        } else if (x == other.x) {
            return y < other.y;
        }
        return false;
    }
};

int main() {
    Point p1(1, 2);
    Point p2(3, 4);
    Point p3(1, 3);

    if (p1 < p2) {
        std::cout << "p1 < p2" << std::endl;
    } else {
        std::cout << "p1 >= p2" << std::endl;
    }

    if (p1 < p3) {
        std::cout << "p1 < p3" << std::endl;
    } else {
        std::cout << "p1 >= p3" << std::endl;
    }

    return 0;
}

 

operator< 函数定义了一种比较规则:先比较 x 坐标,如果 x 坐标相等,则比较 y 坐标。

四、操作符重载的注意事项

4.1 操作符重载的限制

  • 只能重载已有的操作符,不能创建新的操作符。
  • 不能改变操作符的优先级和结合性。
  • 部分操作符(如 ::..*?: 等)不能被重载。

4.2 成员函数和非成员函数重载

操作符重载可以作为类的成员函数或非成员函数实现。一般来说,赋值操作符 =、下标操作符 []、函数调用操作符 () 等通常作为成员函数重载,而二元操作符(如 +-*/ 等)可以作为成员函数或非成员函数重载。

4.3 保持操作符的语义一致性

在重载操作符时,应尽量保持操作符的语义与内置类型的语义一致,避免造成混淆。例如,重载 + 操作符应该实现加法的语义,而不是减法。

五、总结

通过操作符重载,我们可以为自定义类对象赋予与内置类型相似的操作能力,从而提高代码的可读性和可维护性。在重载算数操作符和关系操作符时,需要注意操作符的语义一致性、重载的限制以及成员函数和非成员函数的选择。希望本文能帮助你更好地理解和掌握 C++ 中操作符重载的相关知识。

六、代码示例总结

6.1 复数类 Complex 完整代码 

#include <iostream>

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // 重载加法操作符
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }

    // 重载减法操作符
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }

    // 重载乘法操作符
    Complex operator*(const Complex& other) const {
        double newReal = real * other.real - imag * other.imag;
        double newImag = real * other.imag + imag * other.real;
        return Complex(newReal, newImag);
    }

    // 重载除法操作符
    Complex operator/(const Complex& other) const {
        double denominator = other.real * other.real + other.imag * other.imag;
        double newReal = (real * other.real + imag * other.imag) / denominator;
        double newImag = (imag * other.real - real * other.imag) / denominator;
        return Complex(newReal, newImag);
    }

    // 重载 += 操作符
    Complex& operator+=(const Complex& other) {
        real += other.real;
        imag += other.imag;
        return *this;
    }

    void display() const {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
};

int main() {
    Complex c1(1, 2);
    Complex c2(3, 4);

    Complex sum = c1 + c2;
    Complex diff = c1 - c2;
    Complex prod = c1 * c2;
    Complex quot = c1 / c2;

    std::cout << "c1: ";
    c1.display();
    std::cout << "c2: ";
    c2.display();

    std::cout << "c1 + c2: ";
    sum.display();
    std::cout << "c1 - c2: ";
    diff.display();
    std::cout << "c1 * c2: ";
    prod.display();
    std::cout << "c1 / c2: ";
    quot.display();

    c1 += c2;
    std::cout << "c1 after c1 += c2: ";
    c1.display();

    return 0;
}

 

6.2 点类 Point 完整代码

#include <iostream>

class Point {
private:
    int x;
    int y;
public:
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}

    // 重载相等操作符
    bool operator==(const Point& other) const {
        return (x == other.x) && (y == other.y);
    }

    // 重载 < 操作符
    bool operator<(const Point& other) const {
        if (x < other.x) {
            return true;
        } else if (x == other.x) {
            return y < other.y;
        }
        return false;
    }
};

int main() {
    Point p1(1, 2);
    Point p2(1, 2);
    Point p3(3, 4);
    Point p4(1, 3);

    if (p1 == p2) {
        std::cout << "p1 and p2 are equal." << std::endl;
    } else {
        std::cout << "p1 and p2 are not equal." << std::endl;
    }

    if (p1 == p3) {
        std::cout << "p1 and p3 are equal." << std::endl;
    } else {
        std::cout << "p1 and p3 are not equal." << std::endl;
    }

    if (p1 < p3) {
        std::cout << "p1 < p3" << std::endl;
    } else {
        std::cout << "p1 >= p3" << std::endl;
    }

    if (p1 < p4) {
        std::cout << "p1 < p4" << std::endl;
    } else {
        std::cout << "p1 >= p4" << std::endl;
    }

    return 0;
}

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byte轻骑兵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值