运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。
函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
简单举两个例子说明:
Box operator+(const Box&);
声明加法运算符用于把两个 Box 对象相加,返回最终的 Box 对象。这明显是个类成员函数的运算符重载,所以只需要显示传入一个参数即可。(如果这里不理解,可以学习下this指针)
Box operator+(const Box&, const Box&);
而这个声明,就是普通的非成员函数的运算符重载,所以需要传入两个参数。
(1)成员函数运算符重载代码实现
#include "stdafx.h" #include <iostream> class Box{ public: Box(int height, int width); ~Box(){}; Box operator+(Box &); int getBoxHeight() const { return m_nHeight; } int getBoxWidth() const { return m_nWidth; } int getBoxArea() const { return m_nArea; } private: int m_nHeight; int m_nWidth; int m_nArea; }; Box::Box(int height, int width) : m_nHeight(height), m_nWidth(width){ m_nArea = m_nHeight * m_nWidth; } Box Box::operator+(Box &other){ int height = this->m_nHeight + other.m_nHeight; // 这里为什么对象可以直接访问private成员也是个知识点 int width = this->m_nWidth + other.m_nWidth; return Box(height, width); } int main(){ Box b1(5, 10); Box b2(10, 5); Box b3 = b1 + b2; std::cout << "b1's area is " << b1.getBoxArea() << std::endl; std::cout << "b2's area is " << b2.getBoxArea() << std::endl; std::cout << "b3's area is " << b3.getBoxArea() << std::endl; return 0; } 结果显示: b1's area is 50 b2's area is 50 b3's area is 225 请按任意键继续. . .
(2)普通非成员函数运算符重载代码实现
#include "stdafx.h" #include <iostream> class Box{ public: Box(int height, int width); ~Box(){}; int getBoxHeight() const { return m_nHeight; } int getBoxWidth() const { return m_nWidth; } int getBoxArea() const { return m_nArea; } private: int m_nHeight; int m_nWidth; int m_nArea; }; Box::Box(int height, int width) : m_nHeight(height), m_nWidth(width){ m_nArea = m_nHeight * m_nWidth; } Box operator+(Box &b1, Box &b2){ int height1 = b1.getBoxHeight(); // 这里就不能直接通过对象访问类的private成员了 int width1 = b1.getBoxWidth(); int height2 = b2.getBoxHeight(); int width2 = b2.getBoxWidth(); int height = height1 + height2; int width = width1 + width2; return Box(height, width); } int main(){ Box b1(10, 5); Box b2(5, 10); Box b3 = b1 + b2; std::cout << "b1's area is " << b1.getBoxArea() << std::endl; std::cout << "b2's area is " << b2.getBoxArea() << std::endl; std::cout << "b3's area is " << b3.getBoxArea() << std::endl; return 0; } 结果显示: b1's area is 50 b2's area is 50 b3's area is 225 请按任意键继续. . .
(1)除了类属关系运算符 " . " 、成员指针运算符 " .* / -> * " 、作用域运算符 " :: " 、sizeof运算符和三目运算符 " ?: "、预处理符号 " # "。除此以外,C ++ 中的所有运算符都可以重载。
(2)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(3)重载运算符限制在C ++ 语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。
(4)运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。
(5)运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。
(6)运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。
(7)重载为类成员函数时参数个数=原操作数个数-1(后置++、--除外),而重载为友元函数时参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
(8)单目运算符最好重载为成员函数。
(9)对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。(10)对于其它运算符,建议重载为友元函数。
前置++形式:ClassRoom operator++();
后置++形式:ClassRoom& operator++(int)
后置++调用时默认传入一个0。
代码演示
#include "stdafx.h" #include <iostream> class ClassRoom{ public: ClassRoom(int peopleNum) : m_nPeopleNum(peopleNum) {} ~ClassRoom() {}; int getClassRoomPeopleNum() const { return m_nPeopleNum; } ClassRoom operator++(int); ClassRoom& operator++(); private: int m_nPeopleNum; }; ClassRoom ClassRoom::operator++(int){ ClassRoom temp(*this); m_nPeopleNum++; return temp; } ClassRoom& ClassRoom::operator++(){ m_nPeopleNum++; return *this; } int main(){ ClassRoom r(10); int num1 = r.getClassRoomPeopleNum(); std::cout << "原始人数为 " << num1 << std::endl; ClassRoom r1 = r++; int num2 = r1.getClassRoomPeopleNum(); int num3 = r.getClassRoomPeopleNum(); std::cout << "后置++后赋值结果为 " << num2 << std::endl; std::cout << "后置++后原来人数为 " << num3 << std::endl; ClassRoom r2 = ++r; int num4 = r2.getClassRoomPeopleNum(); int num5 = r.getClassRoomPeopleNum(); std::cout << "前置++后赋值结果为 " << num4 << std::endl; std::cout << "后置++后原来人数为 " << num5 << std::endl; return 0; } 结果显示: 原始人数为 10 后置++后赋值结果为 10 后置++后原来人数为 11 前置++后赋值结果为 12 后置++后原来人数为 12 请按任意键继续. . .
参考资料
https://www.runoob.com/cplusplus/cpp-overloading.html
