目录
1.内容
1.1引入
1.2概念
2.使用
2.1格式
2.1.1类中
2.1.2类外
2.2范围
3.补充
3.1自增(减)运算符重载
3.2赋值运算符重载
在掌握运算符重载的概念之前,我们可以先简单来看一段程序进行了解。
#include
class Point {
private:
int _x;
int _y;
public:
Point() {
}
Point(int x, int y) :_x(x), _y(y) {
}
void Show() {
std::cout << "(" << _x << "," << _y << ")" << std::endl;
}
Point Add(const Point& p) {
Point temp;
temp._x = this->_x + p._x;
temp._y = this->_y + p._y;
return temp;
}
};
int main() {
Point p1(1, 1);
Point p2(2, 2);
p1.Show();
p2.Show();
Point p3 = p1.Add(p2);
p3.Show();
return 0;
}
最终上述代码运行结果即为:
代码中我们定义了点Point类,并创建了p1,p2和p3三个对象,其中p3是其余二者之和,求和的具体方法为我们在类中定义实现的Add函数,但这样繁琐且不直观的操作方式,显然是我们在设计代码中不愿意看到的。因此,我们提出运算符重载的概念来进行改善。
运算符重载概念便是,将系统中预定义的运算符用于我们用户自定义的数据类型。从底层逻辑上而言,运算符重载的实质就是函数重载。
在了解完运算符重载的内容之后,我们来学习如何使用,依旧从上述代码中出发, 我们直接使用如下的相加操作会产生报错。
Point p3 = p1 + p2;
报错的内容是:错误:C2676,二进制“+”:“Point”不定义该运算符或到预定义运算符可接收的类型的转换。因此需要我加入运算符重载的内容加以操作。
对于运算符重载的使用格式,我们直接在上述代码中加以使用便于大家学习。我们可以使用两种方式来完成对类的加法重载实现,第一种方法是在类中完成加法的运算符重载,即运算符重载为成员函数时:
Point operator+ (const Point& p) {
Point temp;
temp._x = this->_x + p._x;
temp._y = this->_y + p._y;
return temp;
}
如此我们便可以直接使用如下的两种方式来完成对类中两个对象的相加。
Point p3 = p1 + p2;//隐式调用
Point p3 = p1.operator+ (p2);//显示调用
或者采用第二种方法,我们在类外完成对类中加法的重载,不过我们需要注意这样的方式我们需要加以友元才可实现。因为类外定义的运算符重载,使用到了类中的私有成员,所以对于类外的运算符重载内容,我们需要在类中定义它为友元。
Point operator+ (const Point& p1, const Point& p2) {
Point temp;
temp._x = p1._x + p2._x;
temp._y = p1._y + p2._y;
return temp;
}
在类外定义加法运算符重载,之后在类中声明为友元:
friend Point operator+ (const Point& p1, const Point& p2);
如此便可完成对类中对象的加法重载。对于第二种的重载方式,当我们在类中提供对外的私有成员返回接口时,虽然我们可以通过相关接口返回得到具体的p1和p2对象内容,但是我们依然无法改变temp对象中的数据成员内容,所以我们只能通过友元来完成。(因为运算符重载涉及到到私有数据成员的改变,我们不能只访问)
在C++中,可以重载的函数运算符有很多,我们列表进行说明:
运算符名称 | 运算符符号 |
算数运算符 |
+、-、*、/、% |
关系运算符 | ==、!!=、<、>、>=、<= |
逻辑运算符 | &&、 ||、! |
赋值运算符 | =、+=、-=、*=、/=、%=…… |
位运算符 | |、&、~、^、<<、>> |
单目运算符 | +、-、*、& |
自增、自减运算符 | ++、-- |
动态内存操作运算符 | new、delete、delete[] |
其他 | ()、[] |
这无疑是很多的,所以我们可以方向记忆,即探究不可重载的运算符内容,如下:
运算符名称 | 运算符符号 |
成员访问运算符 | . |
成员指针运算符 | * |
域操作运算符 |
:: |
条件运算符 | ? : |
空间计算运算符 | sizeof |
对于运算符重载的使用,我们还需明确几点内容,即:
这部分内容我们先来讨论如何重载实现自增和自减,因为在具体重载过程中,我们并无具体的内容置于++(--)前后,所以在重载时,仅通过++(--)是无法判断是前置和后置的,因此我们在实现自增和自减的重载时,会加入无内容的int数据来区分,如下所示:
//前置
Point operator++() {
this->_x++;
this->_y++;
return *this;
}
//后置
Point operator++(int) {
Point temp = *this;
this->_x++;
this->_y++;
return temp;
}
对于自减运算符同理。
赋值运算符的重载我们需要注意检测是否存在给自己赋值的情况,具体案例如下:
Point operator=(const Point& p) {
if (this != &p) {
this->_x = p._x;
this->_y = p._y;
}
return *this;
}
其中值得考究的细节便是,在考察给自己赋值情况时,我们使用的是指针本身的值,即判断两份地址是否相同。这样进行判断操作可避免我们进行!=运算符的重载。