C++ 运算符重载

在 C++ 中,我们可以定义运算符如何作用于用户定义的类型,如 结构。例如:

+ 运算符用于 int 类型的值时,它会返回它们的和。但是,当它用于用户定义类型的对象时,则会引发错误。

在这种情况下,我们可以定义 + 运算符的行为,使其也能用于对象。

这种让运算符作用于对象和结构变量的概念称为 **运算符重载**。


C++ 运算符重载的语法

重载运算符的语法类似于 函数,只是增加了 operator 关键字,后面跟着运算符符号。

returnType operator symbol (arguments) {
    ... .. ...
} 

这里,

  • returnType - 函数的返回类型
  • operator - 一个特殊的 关键字
  • symbol - 我们要重载的运算符(+<-++ 等)
  • arguments - 传递给函数的参数

重载二进制 + 运算符

以下程序演示了如何为 Complex 类重载 + 运算符。

// C++ program to overload the binary operator +
// This program adds two complex numbers

#include <iostream>
using namespace std;

class Complex {
    private:
        float real;
        float img;

    public:
         // constructor to initialize real and img to 0
         Complex() : real(0), img(0) {}
         Complex(float real, float img) : real(real), img(img){}

       // overload the + operator
         friend Complex operator + (const Complex& obj1, const Complex& obj2) {
             Complex temp;
              temp.real = obj1.real + obj2.real;
              temp.img = obj1.img + obj2.img;
              return temp;
    }

    void display() {
        if (img < 0)
            cout << "Output Complex number: " << real << img << "i";
      else
           cout << "Output Complex number: " << real << "+" << img << "i";
    }
};

int main() {
    Complex c1(1.0f, 2.0f);
    Complex c2(1.0f, 3.0f);

    // calls the overloaded + operator
    Complex result = c1 + c2;
    result.display();

    return 0;
}

输出

Output Complex number: 2+5i

在这里,我们首先创建了一个返回类型为 Complex 的友元函数。

friend Complex operator + () {
    ...
}

operator 关键字后跟 + 表示我们正在重载 + 运算符。

该函数接受两个参数

friend Complex operator + (const Complex& obj1, const Complex& obj2) {...}

这里,

  • Complex& 表示我们通过引用传递对象,并且 obj1obj2Complex 对象的引用。这是一种高效的方法,因为它可以避免不必要的复制,特别是对于大对象。要了解更多信息,请访问 C++ 引用
  • const 表示引用的对象是常量,这意味着我们不能在函数中修改 obj1obj2

在函数内部,我们创建了另一个 Complex 对象 temp 来存储加法结果。

Complex temp;

然后,我们将两个对象的实部相加,并将结果存储到 temp 对象的 real 属性中。

temp.real = obj1.real + obj2.real;

同样,我们将两个对象的虚部相加,并将它们存储到 temp 对象的 img 属性中。

temp.img = obj1.img + obj2.img;

最后,我们从函数返回 temp 对象。

return temp;
使用友元函数重载运算符的原因

我们也可以使用成员函数而不是友元函数来重载运算符。例如:

class Complex{
  …..
   public: 
      Complex operator + (const Complex& obj){
          Complex temp;
           temp.real = real + obj.real;
           temp.img = img + obj.img;
           return temp;
  }
  …….
};

在这种情况下,运算符由第一个操作数调用。这意味着,行

Complex c3 = c1 + c2;

被翻译为

c1.operator+(c2);

在这里,运算符函数的参数数量减少了一个,因为第一个参数用于调用函数。

这种方法的缺点是,第一个操作数并不总是用户定义类型的对象。例如:

c2 = 1 + c1;

这就是为什么通常建议将运算符函数重载为非成员函数,并将其定义为友元函数。


重载 ++ 作为前缀运算符

以下程序演示了为 Count 类重载 ++ 运算符。

// Overload ++ when used as a prefix operator

#include <iostream>
using namespace std;

class Count {
    private:
        int value;

   public:

    // constructor to initialize count to 5
    Count() : value(5) {}

    // overload ++ when used as prefix
    void operator ++ () {
        ++value;
    }

    void display() {
        cout << "Count: " << value << endl;
    }
};

int main() {
    Count count1;

    // call the "void operator ++ ()" function
    ++count1;

    count1.display();
    return 0;
}

输出

Count: 6

在这里,当我们使用 ++count1; 时,会调用 void operator ++ ()。这将 count1 对象的值属性增加 1。

注意:重载运算符时,我们可以随意使用它们。例如,我们可以使用 ++ 将值增加 100。

然而,这会使我们的代码令人困惑且难以理解。作为程序员,我们的工作是正确地、以一致且直观的方式使用运算符重载。

重载 ++ 作为后缀运算符

要将 ++ 运算符重载为后缀运算符,我们需要声明一个成员函数 operator++(),该函数接受一个类型为 int 的参数。

// Overload ++ when used as postfix operator

#include <iostream>
using namespace std;

class Count {
   private:
    int value;

   public:

    // constructor to initialize count to 5
    Count() : value(5) {}

    // overload ++ used as postfix
    void operator ++ (int) {
        value++;
    }

    void display() {
        cout << "Count: " << value << endl;
    }
};

int main() {
    Count count1;

    // call the "void operator ++ (int)" function
    count1++;
    count1.display();

    count1.display();
    return 0;
}

输出

Count: 6
Count: 7

在这里,当我们使用 count1++; 时,会调用 void operator ++ (int)。这将 count1 对象的值属性增加 1。

注意:参数 int 仅用于指示运算符被用作后缀运算符。


C++ 运算符重载需要注意的事项

1. 默认情况下,C++ 中 =& 运算符已重载。例如:

我们可以直接使用 = 运算符来复制同一类的对象。在这里,我们不需要创建运算符函数。

2. 我们不能使用运算符重载来更改运算符的优先级和结合性。

3. 我们不能在 C++ 中重载以下运算符:

  • :: (作用域解析)
  • . (成员选择)
  • .* (通过指向函数的指针进行成员选择)
  • ?: (三元运算符)
  • sizeof 运算符
  • typeid 运算符

4. 我们不能为基本数据类型(如 intfloat 等)重载运算符。


另请阅读

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战