c++运算符的重载关键词 (重载运算符有几个参数)

一元运算符重载

上一章说到运算符重载的基础知识,本章则对运算符的重载过程进行深入讲解。首先是一元运算符重载,其方法如图所示:

c++运算符重载,菜鸟教程c++运算符重载

一元运算符重载

一元运算符只对一个操作数进行操作,主要包括:

  • 递增运算符(++)和递减运算符(--)
  • 一元减运算符,即负号(-)
  • 逻辑非运算符(!)

其中递增运算符(++)和递减运算符(--)是一元运算符重载中的重点,下面是使用友元重载运算符++、--、- 的例子。

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
private:
  friend Complex& operator++(Complex& c1); //全局函数,重载前置++
  friend Complex operator++(Complex& c1, int); //全局函数,重载后置++
  friend Complex& operator--(Complex& c1); //全局函数,重载前置--
  friend Complex operator--(Complex& c1, int); //全局函数,重载后置--
  friend Complex& operator-(Complex& c1); //全局函数,重载负号-
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
     cout << a << " + " << b << "i" << endl;
  }
};
//前置++, c1私有成员先++,后返回c1++之后的对象
Complex& operator++(Complex & c1)
{
  c1.a++;
  c1.b++;
  return c1;
}
//后置++,c1私有成员先++,返回c1++之前的对象
Complex operator++(Complex & c1, int)
{
  Complex tmp = c1;
  c1.a++;
  c1.b++;
  return tmp;
}
//前置--,c1私有成员先--,后返回c1--之后的对象
Complex& operator--(Complex& c1)
{
  c1.a--;
  c1.b--;
  return c1;
}
//后置--,c1私有成员先--,返回c1--之前的对象
Complex operator--(Complex& c1, int)
{
  Complex tmp = c1;
  c1.a--;
  c1.b--;
  return tmp;
}
// 重载负运算符( - )
Complex& operator-(Complex& c1)
{
  c1.a = -c1.a;
  c1.b = -c1.b;
  return c1;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //前置++操作符 用全局函数实现
  ++c1;
  operator++(c1); //等于++c1
  c1.print();
  //前置--操作符 用全局函数实现
  --c1;
  operator--(c1); //等于--c1
  c1.print();
  //后置++操作符 用全局函数实现
  c1++;
  operator++(c1, 0); //等于c1++
  c1.print();
  //后置--操作符 用全局函数实现
  c1--;
  operator--(c1, 0); //等于c1--
  c1.print();
  //负号-操作符
  -c1;
  c1.print();
  operator-(c1); //等于-c1
  c1.print();
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

使用成员函数重载两种运算符的例子:

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
public:
  Complex& operator++(); //成员函数,重载前置++
  Complex operator++(int); //成员函数,重载后置++
  Complex& operator--(); //成员函数,重载前置--
  Complex operator--(int); //成员函数,重载后置--
  Complex& operator-(); //成员函数,重载负号-
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
     cout << a << " + " << b << "i" << endl;
  }
};
//前置++, c1私有成员先++,后返回c1++之后的对象
Complex& Complex::operator++()
{
  this->a++;
  this->b++;
  return *this;
}
//后置++,c1私有成员先++,返回c1++之前的对象
Complex Complex::operator++(int)
{
  Complex tmp = *this;
  this->a++;
  this->b++;
  return tmp;
}
//前置--,c1私有成员先--,后返回c1--之后的对象
Complex& Complex::operator--()
{
  this->a--;
  this->b--;
  return *this;
}
//后置--,c1私有成员先--,返回c1--之前的对象
Complex Complex::operator--(int)
{
  Complex tmp = *this;
  this->a--;
  this->b--;
  return tmp;
}
// 重载负运算符( - )
Complex& Complex::operator-()
{
  this->a = -this->a;
  this->b = -this->b;
  return *this;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //前置++操作符 用成员函数实现
  ++c1;
  c1.operator++(); //等于++c1
  c1.print();
  //前置--操作符 用成员函数实现
  --c1;
  c1.operator--(); //等于--c1
  c1.print();
  //后置++操作符 用成员函数实现
  c1++;
  c1.operator++(0); //等于c1++
  c1.print();
  //后置--操作符 用成员函数实现
  c1--;
  c1.operator--(0); //等于c1--
  c1.print();
  //负号-操作符
  -c1;
  c1.print();
  c1.operator-(); //等于-c1
  c1.print();
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

从上面的例子可以看出, C++中通过一个占位参数来区分前置运算和后置运算,可以总结为:

c++运算符重载,菜鸟教程c++运算符重载

运算符++和--重载方式

二元运算符重载

二元运算符意味着需要两个参数,而平常使用的加运算符(+)、减运算符(-)、乘运算符(*)和除运算符(/)都属于二元运算符。下面的实例演示了如何重载二元运算符。

使用友元重载二元运算符例子:

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
private:
  friend Complex operator+(Complex& c1, Complex& c2);//全局函数, 重载+运算符
  friend Complex operator-(Complex& c1, Complex& c2); //全局函数, 重载-运算符
  friend Complex operator*(Complex& c1, Complex& c2); //全局函数, 重载*运算符
  friend Complex operator/(Complex& c1, Complex& c2); //全局函数, 重载/运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//全局函数法实现+运算符重载
Complex operator+(Complex& c1, Complex& c2)
{
  Complex tmp(c1.a + c2.a, c1.b + c2.b);
  return tmp;
}
//全局函数法实现-运算符重载
Complex operator-(Complex & c1, Complex & c2)
{
  Complex tmp(c1.a - c2.a, c1.b - c2.b);
  return tmp;
}
//全局函数法实现*运算符重载
Complex operator*(Complex& c1, Complex& c2)
{
  Complex tmp(c1.a * c2.a, c1.b * c2.b);
  return tmp;
}
//全局函数法实现/运算符重载
Complex operator/(Complex& c1, Complex& c2)
{
  Complex tmp(c1.a / c2.a, c1.b / c2.b);
  return tmp;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //1	全局函数法实现+运算符重载
  Complex c3 = c1 + c2;
  Complex c4 = operator+(c1, c2); //等于Complex c3 = c1 + c2;
  c3.print();
  c4.print();
  //2 全局函数法实现-运算符重载
  Complex c5 = c1 - c2;
  Complex c6 = operator-(c1, c2);  //等于Complex c5 = c1 - c2;
  c5.print();
  c6.print();
  //3 全局函数法实现*运算符重载
  Complex c7 = c1 * c2;
  Complex c8 = operator*(c1, c2); //等于Complex c7 = c1 * c2;
  c7.print();
  c8.print();
  //4 全局函数法实现/运算符重载
  Complex c9 = c2 / c1;
  Complex c10 = operator/(c2, c1); //等于Complex c9 = c2 / c1;
  c9.print();
  c10.print();
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

使用成员函数重载二元运算符例子:

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
public:
  Complex operator+(Complex& c2); //成员函数, 重载+运算符
  Complex operator-(Complex& c2); //成员函数, 重载-运算符
  Complex operator*(Complex& c2); //成员函数, 重载*运算符
  Complex operator/(Complex& c2); //成员函数, 重载/运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//成员函数法实现+运算符重载
Complex Complex::operator+(Complex& c2)
{
  Complex tmp(this->a + c2.a, this->b + c2.b);
  return tmp;
}
//成员函数法实现-运算符重载
Complex Complex::operator-(Complex & c2)
{
  Complex tmp(this->a - c2.a, this->b - c2.b);
  return tmp;
}
//成员函数法实现*运算符重载
Complex Complex::operator*(Complex & c2)
{
  Complex tmp(this->a * c2.a, this->b * c2.b);
  return tmp;
}
//成员函数法实现/运算符重载
Complex Complex::operator/(Complex & c2)
{
  Complex tmp(this->a / c2.a, this->b / c2.b);
  return tmp;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //1	成员函数法实现+运算符重载
  Complex c3 = c1 + c2;
  Complex c4 = c1.operator+(c2); //等于Complex c3 = c1 + c2;
  c3.print();
  c4.print();
  //2 成员函数法实现-运算符重载
  Complex c5 = c1 - c2;
  Complex c6 = c1.operator-(c2); //等于Complex c5 = c1 - c2;
  c5.print();
  c6.print();
  //3 成员函数法实现*运算符重载
  Complex c7 = c1 * c2;
  Complex c8 = c1.operator*(c2); //等于Complex c7 = c1 * c2;
  c7.print();
  c8.print();
  //4 成员函数法实现/运算符重载
  Complex c9 = c2 / c1;
  Complex c10 = c2.operator/(c1); //等于Complex c9 = c2 / c1;
  c9.print();
  c10.print();
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

从上面两个例子可以看出,成员函数法与全局函数法相比是将 Complex & c1 使用 this 指针替代, 同时要注意c1和c2的顺序

关系运算符重载

C++ 语言支持各种关系运算符( < 、 > 、 <= 、 >= 、 == 等等),它们可用于比较 C++ 内置的数据类型。在项目开发中可以重载任何一个关系运算符,重载后的关系运算符可用于比较类的对象。下面的实例演示了如何重载 >、<、== 运算符:

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
public:
  bool operator<(Complex& c2); //成员函数, 重载<运算符
  bool operator>(Complex& c2); //成员函数, 重载>运算符
  bool operator==(Complex& c2); //成员函数, 重载==运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//成员函数法实现<运算符重载
bool Complex::operator<(Complex& c2)
{
  if ((this->a < c2.a) && (this->b < c2.b))
  {
    return true;
  }
  else
  {
    return false;
  }
}
//成员函数法实现>运算符重载
bool Complex::operator>(Complex & c2)
{
  if ((this->a > c2.a) && (this->b > c2.b))
  {
    return true;
  }
  else
  {
    return false;
  }
}
//成员函数法实现==运算符重载
bool Complex::operator==(Complex & c2)
{
  if ((this->a == c2.a) && (this->b == c2.b))
  {
    return true;
  }
  else
  {
    return false;
  }
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  Complex c3(3, 4);
  //1 成员函数法实现>运算符重载
  if (c2 > c1)
  {
    cout << "c2 > c1" << endl;
  }
  //2 成员函数法实现<运算符重载
  if (c1 < c2)
  {
    cout << "c1 < c2" << endl;
  }
  //3 成员函数法实现==运算符重载
  if (c2 == c3)
  {
    cout << "c2 == c3" << endl;
  }
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

输入/输出运算符重载

C++ 能够使用流提取运算符 >> 和流插入运算符 << 来输入和输出内置的数据类型。在项目开发中可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型;不过有一点很重要,需要把运算符重载函数声明为类的友元函数,这样就能不用创建对象而直接调用函数。下面的实例演示了如何重载提取运算符 >> 和插入运算符 <<。

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
private:
  friend istream& operator>>(istream& ios, Complex& c1); //全局函数, 重载>>运算符
  friend ostream& operator<<(ostream& oos, const Complex& c1); //全局函数, 重载<<运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//全局函数法实现>>运算符重载
istream& operator>>(istream& ios, Complex& c1)
{
  ios >> c1.a >> c1.b;
  return ios;
}
//全局函数法实现<<运算符重载
ostream& operator<<(ostream& oos, const Complex& c1)
{
  oos << c1.a << " + " << c1.b << "i" << endl;
  return oos;
}
//主函数
int main()
{
  Complex c1(1, 2);
  //1 全局函数法实现>>运算符重载
  cout << "please input c1: ";
  cin >> c1;
  c1.print();
  //2 全局函数法实现<<运算符重载
  cout << "output: " << c1 << endl;
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

赋值运算符重载

在项目开发中可以重载赋值运算符(=),用于创建一个对象,比如拷贝构造函数。

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
public:
  void operator=(const Complex& c2); //重载=运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//实现=运算符重载
void Complex::operator=(const Complex& c2)
{
  this->a = c2.a;
  this->b = c2.b;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //1 成员函数法实现=运算符重载
  c1 = c2;
  c1.print(); //输出3 + 4i
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

函数调用运算符()重载

在项目开发中函数调用运算符()可以被重载用于类的对象。当重载()时不是创造了一种新的调用函数的方式,相反是创建一个可以传递任意数目参数的运算符函数。下面的实例演示了如何重载函数调用运算符 ()。

#include <iostream>
using namespace std;
class Complex
{
private:
  int a;
  int b;
public:
  Complex& operator()(const Complex& c2); //重载()运算符
public:
  Complex(int a = 0, int b = 0)
  {
    this->a = a;
    this->b = b;
  }
  void print()
  {
    cout << a << " + " << b << "i" << endl;
  }
};
//实现=运算符重载
Complex& Complex::operator()(const Complex& c2)
{
  this->a *= c2.a;
  this->b *= c2.b;
  return *this;
}
//主函数
int main()
{
  Complex c1(1, 2);
  Complex c2(3, 4);
  //1 成员函数法实现()运算符重载
  c1 = c1(c2);
  c1.print(); //输出3 + 8i
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

上面例子中使用重载()运算符实现 c1*c2

下标运算符[]重载

下标操作符 [] 通常用于访问数组元素。在项目开发中重载该运算符用于增强操作C++数组的功能。下面的实例演示了如何重载下标运算符 []

#include <iostream>
using namespace std;
const int SIZE = 10;
class Complex
{
private:
  int arr[SIZE];
public:
  Complex()
  {
    register int i;
    for (i = 0; i < SIZE; i++)
    {
      arr[i] = i;
    }
  }
  int& operator[](int i)
  {
    if (i > SIZE)
    {
      cout << "索引超过最大值" << endl;
      // 返回第一个元素
      return arr[0];
    }
    return arr[i];
  }
};
//主函数
int main()
{
  Complex c1;
  cout << "c1[2] 的值为 : " << c1[2] << endl; //输出2
  cout << "c1[5] 的值为 : " << c1[5] << endl; //输出5
  cout << "c1[12] 的值为 : " << c1[12] << endl; //输出第一个元素0
  cout << "hello..." << endl;
  system("pause");
  return 0;
}

运算符重载注意点

  • 运算重载符不可以改变语法结构。
  • 运算重载符不可以改变操作数的个数。
  • 运算重载符不可以改变优先级。
  • 运算重载符不可以改变结合性。

this 指针的作用

this 指针是一个隐含于每一个非静态成员函数中的特殊指针,它指向正在被该成员函数操作的那个对象。当对一个对象调用成员函数时,编译器先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时由隐含使用 this 指针。