重载运算符

  • 重载运算符的本质是函数,其名字由operator关键字后接表示要定义的运算符的符号组成

  • 因此,赋值运算符就是一个名为operator=的函数。

  • 类似于任何其他的函数,重载运算符函数也有一个返回类型和一个参数列表。

  • 重载运算符的参数是表示重载运算符要去操作的运算对象。对于某些运算符,包括赋值运算符,都必须定义为成员函数。

运算符重载

运算符重载是C++中的一种特性,它允许我们为自定义数据类型(如类和结构)定义运算符的行为。这意味着我们可以使用现有的运算符来操作我们定义的类型,使代码更加直观和易于理解。

让我们从一个简单的示例开始,创建一个名为“Fraction”的分数类,我们将重载加法运算符(+)来处理两个分数的相加。

#include <iostream>

class Fraction {
public:
    // 构造函数
    Fraction(int numerator, int denominator) : numerator_(numerator), denominator_(denominator) {}

    // 获取分子
    int GetNumerator() const {
        return numerator_;
    }

    // 获取分母
    int GetDenominator() const {
        return denominator_;
    }

    // 重新定义 Fraction 这个类型的 + 运算符。
    Fraction operator+(const Fraction& other) const {
        int commonDenominator = denominator_ * other.denominator_;
        int newNumerator = (numerator_ * other.denominator_) + (other.numerator_ * denominator_);

        return Fraction(newNumerator, commonDenominator);
    }

private:
    int numerator_; //分子
    int denominator_; //分母
};

int main() {
    Fraction frac1(1, 2);
    Fraction frac2(1, 3);

    Fraction result = frac1 + frac2; // 使用重载后的加法运算符

    std::cout << "Result: " << result.GetNumerator() << "/" << result.GetDenominator() << std::endl;
    return 0;
}

  • 在这个例子中,我们定义了一个名为Fraction的类,它有两个私有成员变量:numerator_(分子)和denominator_(分母)。我们还定义了一个名为operator+的成员函数,它接受一个Fraction对象的引用作为参数,并返回一个新的Fraction对象。这个函数的实现是根据两个分数的加法规则计算出新的分子和分母。

  • 在main()函数中,我们创建了两个Fraction对象,并使用重载的加法运算符(+)将它们相加。最后,我们将结果打印到控制台。

  • 这只是一个简单的示例,C++允许我们重载许多不同的运算符,例如-、*、/、%、==、!=、<、>、<=、>=、++、--、+=、-=、*=、/=、%=、&、|、^、~、<<、>>、>>=、<<=、!、&&、||、[]、()、->、->*、,和new、delete、new[]、delete[]等等。

需要遵守的原则

  • 当重载运算符时,请确保您遵循一些基本原则:
  1. 保持操作符的语义:尽量让重载的运算符具有类似的行为和语义,以避免引入混淆或误导性的代码。

  2. 不要滥用运算符重载:虽然运算符重载可以让代码更易读,但不当使用会导致代码难以理解。请确保重载的运算符适用于您的类,并确保其实现与期望的行为一致。

  3. 使用成员函数和非成员函数进行重载:某些运算符应该作为类的成员函数重载(例如 +=、-=),而另一些运算符应该作为非成员函数重载(例如 +、-)。这取决于运算符的语义以及您希望在类之外使用哪些重载运算符。

以下是另一个Fraction类的示例,这次我们将添加一个友元函数来重载输出运算符(<<):

#include <iostream>
#include <string>
using namespace std;
class Fraction {
public:
    Fraction(int numerator, int denominator) : numerator_(numerator), denominator_(denominator) {}

    int GetNumerator() const {
        return numerator_;
    }

    int GetDenominator() const {
        return denominator_;
    }

    Fraction operator+(const Fraction& other) const {
        int commonDenominator = denominator_ * other.denominator_;
        int newNumerator = (numerator_ * other.denominator_) + (other.numerator_ * denominator_);

        return Fraction(newNumerator, commonDenominator);
    }

    // 重载输出运算符(友元函数)
    friend std::ostream& operator<<(std::ostream& os, const Fraction& fraction);

private:
    int numerator_;
    int denominator_;
};

// 实现重载输出运算符(非成员函数)
std::ostream& operator<<(std::ostream& os, const Fraction& fraction) {
    os << fraction.numerator_ << "/" << fraction.denominator_;
    return os;
}

int main() {
    Fraction frac1(1, 2);
    Fraction frac2(1, 3);
    cout<<"frac1 = "<<frac1<<endl;
    cout<<"frac2 = "<<frac2<<endl;
    Fraction result = frac1 + frac2;

    std::cout << "Result = " <<frac1<<" + "<<frac2<<" = "<< result << std::endl; // 使用重载的输出运算符
    return 0;
}
  • 在这个例子中,我们添加了一个名为operator<<的友元函数,用于重载输出运算符。这使得我们可以直接在std::cout语句中输出Fraction对象,而不需要调用GetNumerator()GetDenominator()函数。

总之,运算符重载是C++中一种强大的特性,可以让我们为自定义类型定义运算符的行为。请务必合理地使用这个特性,以便编写出易于阅读和理解的代码。

总结

我原来在看C++Primer5的时候,第一开始就给我一堆我看不懂的代码,然后其中最看不懂的就是这个operator关键字,原来我还不知道是啥意思,今天我死磕了好几个小时,终于给我弄懂了!!!

03-29 23:43