运算符重载
运算符重载的特点
可以将运算符实际就是函数,运算符重载实际就是函数重载,运算符重载有两种形式:重载为类的成员函数,重载为类的非成员函数(一般为友元)。
重载为类的成员函数时,函数的参数个数比原来的操作数要少一个
(this作为一个成员,另一个对象作为另一个成员)
1、双目运算符重载为类的成员函数时,函数只显示说明一个参数,该形参是运算符的右操作数。(a+b)
2、前置单目运算符重载为类的成员函数时,不需要显示说明参数,即该函数没有形参。(++a)
3、后置单目运算符重载为类的成员函数时,函数要带有一个整形形参。(a++)
重载为类的非成员函数时,函数的参数个数一般为两个
成员函数运算符与友元函数运算符的异同
- 一般情况下,单目运算符最好重载为类的成员函数;双目运算符最好重载为类的友元函数
- 若运算符所需的操作数希望有隐式类型转换,则只能选择友元函数。
- 当运算符函数是一个成员函数时,最左边的操作数必须是运算符类的一个类对象。
不可重载的运算符
. 类属关系运算符
.* 成员指针运算符
:: 作用域运算符
? : 条件运算符
#:编译预处理符号
sizeof() 取数据类型的长度
左值Lvalue与右值Rvalue
左值:能出现在赋值运算符“=”的左边,能被赋值;
右值:出现在赋值运算符“=”的右边,不能被赋值。
是不是尽量都重载为一个左值?
例:重载r1[i];
double& Vec2D::operator[](const int index)
{
if (index == 0)return x;
else if (index == 1)return y;
else cout << "检索超过范围" << endl;
}
在double后面加一个&,就表示重载为左值,此时可以进行赋值。
重载自增自减运算符
PS:C语言里头,前自增和后自增都是一个右值,在C++里头看你怎么重载的自增运算符!
前置与后置的区别
前置重载无参数,返回引用类型。
后置重载带参数,一般使用一个int来区别,但是不参与运算。
重载流提取运算符(<<,>>)
只能重载为友元函数
原因如下:使用<<和>>运算符时,第一个参数是流类的实例:cout<<x<<y;但是如果重载为类成员函数,当调用该运算符后,左操作数必须是该类的实例,形式为 r1<<cout;不符合使用习惯,因此只能重载为友元
istream& operator>>(istream& steam, Vec2D& v1)
{
// TODO: 在此处插入 return 语句
steam >> v1[0] >> v1[1];
return steam;
}
代码示例
通过运算符重载实现一个向量类Vec2D,可以使以下测试代码编译通过。
#include <iostream>
#include "Vec2D.h"
using std::cout;
using std::endl;
int main() {
// 创建向量对象
Vec2D v1{ 3,5 }, v2{ 4,6 };
// 向量转为字符串
cout << "v1 = " << v1.toString() << endl;
cout << "v2 = " << v2.toString() << endl;
// 向量加法: 向量+向量,向量+数
Vec2D v3 = v1 + v2;
Vec2D v4 = v3 + 10.0;
cout << "v3 = " << v3.toString() << endl;
cout << "v4 = " << v4.toString() << endl;
// 向量减法,向量点积,向量数乘
Vec2D v5 = v2 - v1;
double v6 = v2 * v1;
Vec2D v7 = 2.1 * v3;
cout << "v2 - v1 = " << v5.toString() << endl;
cout << "v2 . v1 = " << v6 << endl;
cout << "v3 * 2.1 = " << (v3 * 2.1).toString() << endl;
cout << "2.1 * v3 = " << v7.toString() << endl;
Vec2D va1{ 10, 12 }, va2{ 1, 2 };
cout << " va1 += va2 : " << (va1 += va2).toString() << endl;
cout << " va1 -= va2 : " << (va1 -= va2).toString() << endl;
// 向量求负值
Vec2D v8 = v2.negative();
cout << "-v2 = " << (-v2).toString() << endl;
// 向量自增/自减
cout << "++v8 = " << (++v8).toString() << endl;
cout << "v8++ = " << (v8++).toString() << endl;
cout << "v8 = " << v8.toString() << endl;
cout << "--v2 = " << (--v2).toString() << endl;
// 读取或者修改向量元素
v1[0] = 31.1;
cout << "v1.x_ = " << v1[0] << endl;
cout << "v1.y_ = " << v1[1] << endl;
// v1[ 8 ] = 10.0;
// 向量的长度magnitude 和角度direction
cout << "v1.magnitude = " << v1.magnitude() << endl;
cout << "double(v1) = " << static_cast<double>(v1) << endl;
cout << "v1.direction = " << v1.direction() << endl;
// 比较两个向量
cout << "v1 compare v2 : " << v1.compareTo(v2) << endl;
cout << "Please input a Vec2D:";
Vec2D v9{};
std::cin >> v9; // operator>>(std::cin, v9);
cout << v9 << endl;
}
完整代码:
#define M_PI 3.14159265358979323846
#include <iostream>
#include <string>
using namespace std;
class Vec2D
{
private:
double x = 0.000000;
double y = 0.000000;
public:
Vec2D(int a, int b)
:x(a), y(b)
{}
Vec2D() {}
string toString();
//向量加法: 向量 + 向量,向量 + 数
Vec2D operator+(const Vec2D& v1);
Vec2D operator+(const double& a);
// 向量减法,向量点积,向量数乘
Vec2D operator-(const Vec2D& v1);
double operator*(const Vec2D& v1);
friend Vec2D& operator*(const double& a, Vec2D& v1);
friend Vec2D operator*(Vec2D& v1, const double& a);
//+= -=
Vec2D& operator+=(const Vec2D& v1);
Vec2D& operator-=(const Vec2D& v1);
// 向量求负值
Vec2D negative();
Vec2D operator-();
// 向量自增/自减
Vec2D& operator++();
Vec2D& operator--();
Vec2D operator++(int dummy);
// 读取或者修改向量元素
double& operator[](const int index);
// 向量的长度magnitude 和角度direction
double magnitude();
explicit operator double()
{
return sqrt(x * x + y * y);
}
double direction();
// 比较两个向量
bool compareTo(Vec2D& v1);
//重载>>和<<
friend ostream& operator<<(ostream& steam, Vec2D& v1);
friend istream& operator>>(istream& steam, Vec2D& v1);
};
int main()
{
// 创建向量对象
Vec2D v1{ 3,5 }, v2{ 4,6 };
// 向量转为字符串
cout << "v1 = " << v1.toString() << endl;
cout << "v2 = " << v2.toString() << endl;
// 向量加法: 向量+向量,向量+数
Vec2D v3 = v1 + v2;
Vec2D v4 = v3 + 10.0;
cout << "v3 = " << v3.toString() << endl;
cout << "v4 = " << v4.toString() << endl;
// 向量减法,向量点积,向量数乘
Vec2D v5 = v2 - v1;
double v6 = v2 * v1;
Vec2D v7 = 2.1 * v3;
cout << "v2 - v1 = " << v5.toString() << endl;
cout << "v2 . v1 = " << v6 << endl;
cout << "v3 * 2.1 = " << (v3 * 2.1).toString() << endl;//设计成一个右值,不可赋值
cout << "2.1 * v3 = " << v7.toString() << endl;
Vec2D va1{ 10, 12 }, va2{ 1, 2 };
cout << " va1 += va2 : " << (va1 += va2).toString() << endl;
cout << " va1 -= va2 : " << (va1 -= va2).toString() << endl;
// 向量求负值
Vec2D v8 = v2.negative();
cout << "-v2 = " << (-v2).toString() << endl;
// 向量自增/自减
cout << "++v8 = " << (++v8).toString() << endl;
cout << "v8++ = " << (v8++).toString() << endl; //这条语句执行完了之后再执行++操作
cout << "v8 = " << v8.toString() << endl;
cout << "--v2 = " << (--v2).toString() << endl;
// 读取或者修改向量元素
v1[0] = 31.1;
cout << "v1.x_ = " << v1[0] << endl;
cout << "v1.y_ = " << v1[1] << endl;
// v1[ 8 ] = 10.0;
// 向量的长度magnitude 和角度direction
cout << "v1.magnitude = " << v1.magnitude() << endl;
cout << "double(v1) = " << static_cast<double>(v1) << endl;
cout << "v1.direction = " << v1.direction() << endl;
// 比较两个向量
cout << "v1 compare v2 : " << v1.compareTo(v2) << endl;
cout << "Please input a Vec2D:";
Vec2D v9{};
std::cin >> v9; // operator>>(std::cin, v9);
cout << v9 << endl;
return 0;
}
string Vec2D::toString()
{
string tmp;
tmp = "(" + to_string(x) + "," + to_string(y) + ")";
return tmp;
}
Vec2D Vec2D::operator+(const Vec2D& v1)
{
Vec2D v3{ 0,0 };
v3.x = this->x + v1.x;
v3.y = this->y + v1.y;
return v3;
}
Vec2D Vec2D::operator+(const double& a)
{
Vec2D v4{ 0,0 };
v4.x = this->x + a;
v4.y = this->y + a;
return v4;
}
Vec2D Vec2D::operator-(const Vec2D& v1)
{
Vec2D v5{ 0,0 };
v5.x = this->x - v1.x;
v5.y = this->y - v1.y;
return v5;
}
double Vec2D::operator*(const Vec2D& v1)
{
return x * v1.x + y * v1.y;
}
Vec2D& operator*(const double& a, Vec2D& v1)
{
Vec2D tmp(0, 0);
tmp.x = a * v1.x;
tmp.y = a * v1.y;
return tmp;
}
Vec2D operator*(Vec2D& v1, const double& a)
{
Vec2D tmp(0, 0);
tmp.x = v1.x * a;
tmp.y = v1.y * a;
return tmp;
}
Vec2D& Vec2D::operator+=(const Vec2D& v1)
{
x = this->x + v1.x;
y = this->y + v1.y;
return *this;
}
Vec2D& Vec2D::operator-=(const Vec2D& v1)
{
x = this->x - v1.x;
y = this->y - v1.y;
return *this;
}
Vec2D Vec2D::negative()
{
Vec2D tmp(0, 0);
tmp.x = -x;
tmp.y = -y;
return tmp;
}
Vec2D Vec2D::operator-()
{
Vec2D tmp(0, 0);
tmp.x = -x;
tmp.y = -y;
return tmp;
}
Vec2D& Vec2D::operator++()
{
x++;
y++;
return *this;
}
Vec2D& Vec2D::operator--()
{
x--;
y--;
return *this;
}
Vec2D Vec2D::operator++(int dummy)
{
Vec2D tmp(0, 0);
//先把值给赋了,然后在执行本对象的自增操作
tmp.x = x;
tmp.y = y;
x++;
y++;
//返回临时对象
return tmp;
}
//能被赋值,肯定是一个左值,可引用
double& Vec2D::operator[](const int index)
{
if (index == 0)return x;
else if (index == 1)return y;
else cout << "检索超过范围" << endl;
}
double Vec2D::magnitude()
{
return sqrt(x * x + y * y);
}
double Vec2D::direction()
{
double tmp = y / (this->magnitude());
tmp = asin(tmp);
return tmp;
}
bool Vec2D::compareTo(Vec2D& v1)
{
if (this->magnitude() > v1.magnitude())return true;
return false;
}
ostream& operator<<(ostream& steam, Vec2D& v1)
{
// TODO: 在此处插入 return 语句
steam << "(" << v1[0] << "," << v1[1] << ")";
return steam;
}
istream& operator>>(istream& steam, Vec2D& v1)
{
// TODO: 在此处插入 return 语句
steam >> v1[0] >> v1[1];
return steam;
}