C++中的运算符重载
程序员可以重定义或重载大部分 C++ 内置的运算符。这样就能使用自定义类型的运算符。重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
运算符重载规则如下:
①、 C++中的运算符除了少数几个之外,全部可以重载,而且只能重载C++中已有的运算符。
②、 重载之后运算符的优先级和结合性都不会改变,但是运算对象的求值顺序无法应用到重载的运算符上。
③、 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来说,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
不能重载的运算符只有五个,它们是:成员运算符“.”、指针运算符“*”、作用域运算符“::”、“sizeof”、条件运算符“?:”。
下面以一个位置坐标position类作为一个例子介绍一些常见的运算符重载,其中position类包含三维坐标x,y,z。主要有输出操作符重载、算术运算符重载、关系运算符重载、自加运算符重载、下标运算符重载。代码中有详细的注解。
overloadtest.h
#pragma once
#include <iostream>
#include <assert.h>
class Position
{
public:
Position() = default;//默认构造函数
Position(double x, double y,
double z) :x(x), y(y), z(z) {};
Position(const Position&pos) = default;
~Position() = default;
//输出操作符重载,由于是类外的函数,访问类内私有变量则应该被定义为友元函数
friend std::ostream& operator<< (std::ostream& out, const Position& pos);
friend bool operator== (const Position& lpos, const Position& rpos);
//算术运算符重载,+=应该定义为类内的成员函数,+应该定义为类外的函数
Position& operator+= (const Position& rpos);
//前置递增运算符重载
Position& operator++ ();
//后置递增运算符重载
Position operator++ (int);
//赋值运算符重载
Position& operator= (const Position& pos);
//下标运算符重载
double& operator[](std::size_t n);
const double& operator[](std::size_t n) const;
private:
double x;
double y;
double z;
};
Position operator+ (const Position& lpos, const Position& rpos);
bool operator!= (const Position& lpos, const Position& rpos);
overloadtest.cpp
#include "overloadtest.h"
//输出操作符重载,约定写在类外而不是成员函数
std::ostream& operator<< (std::ostream& out,const Position& pos)
{
out << pos.x << " " << pos.y << " " << pos.z << " " << std::endl;
return out;
}
//算术运算符重载,+=应该定义为类内的成员函数
Position& Position::operator+= (const Position& rpos)
{
x += rpos.x;
y += rpos.y;
z += rpos.z;
return *this;
}
//算术运算符重载,+应该定义为类外函数
Position operator+ (const Position& lpos, const Position& rpos)
{
Position sum = lpos;
sum += rpos;
return sum;
}
//相等操作符重载,约定写在类外而不是成员函数
bool operator== (const Position& lpos, const Position& rpos)
{
return lpos.x == rpos.x&&lpos.y == rpos.y&&lpos.z == rpos.z;
}
//不等操作符重载,依赖于相等运算符
bool operator!= (const Position& lpos, const Position& rpos)
{
return !(lpos == rpos);
}
//前置递增运算符重载
Position& Position::operator++ ()
{
++x;
++y;
++z;
return *this;
}
//后置递增运算符重载
Position Position::operator++ (int)
{
Position res;
res = *this;
++(*this);
return res;
}
//赋值运算符重载
Position& Position::operator= (const Position& pos)
{
this->x = pos.x;
this->y = pos.y;
this->z = pos.z;
return *this;
}
//下标运算符重载
double& Position::operator[](std::size_t n)
{
if (n < 0 || n>2)
{
std::cout << "越界" << std::endl;
assert(n < 0 || n>2);
}
if (n == 0)
return x;
if (n == 1)
return y;
if (n == 2)
return z;
}
//下标运算符重载
const double& Position::operator[](std::size_t n) const
{
if (n < 0 || n>2)
{
std::cout << "越界" << std::endl;
assert(n < 0 || n>2);
}
if (n == 0)
return x;
if (n == 1)
return y;
if (n == 2)
return z;
}
main.cpp
#include <iostream>
#include "overloadtest.h"
using namespace std;
int main()
{
Position pos(10, 5.0, 6.0);
Position pos1(10, 5.0, 6.0);
Position pos2(1.5, 12.3, -5.8);
Position pos4(pos);
cout << "pos1: " << pos1 << endl;//输出操作符重载
cout << "pos2: " << pos2 << endl;
cout << "pos4: " << pos4 << endl;
pos2 += pos1;//+=运算符重载
cout << "pos2: " << pos2 << endl;
Position pos3 = pos1 + pos1;//+运算符重载
cout << "pos3: " << pos3 << endl;
if (pos == pos1)
{
cout << "pos 等于 pos1" << endl;
}
if (pos != pos2)
{
cout << "pos 不等于 pos2" << endl;
}
cout << "++pos: " << ++pos << endl;
cout << "++pos: " << pos << endl;
cout << "pos++: " << pos++ << endl;
cout << "pos++: " << pos << endl;
Position pos5;
pos5 = pos;//赋值运算符重载
cout << "pos5: " << pos5 << endl;
//下标运算符重载
pos5[0] = 100;
pos5[1] = 10;
pos5[2] = 1;
cout << "pos5: " << pos5 << endl;
system("pause");
return 0;
}