操作符重载规则
- 不能被重载的操作符
符号 | 符号举例 |
---|---|
. | Peron.name |
.* | Person.*name=*(Person.name) |
:: | 作用域操作符 |
?: | 条件操作符 |
- 操作符重载不能改变操作数的个数
- 操作符重载不改变运算顺序(依然先算 * / 后算+ -)
- 操作符重载不改变运算的结合性
- 操作符重载不能有默认参数
- 操作符重载至少要有一个自定义类型
- 操作符重载应当与原来操作符含义相似
- 操作符重载可以是类的成员函数、类的友元函数、还可以是普通函数。
单目运算符
++(左)
- 说明: ++(左)可以进行连+
class Point
{
//friend Point& operator++(Point& p);
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
Point& operator++()
{
++m_x ;
++m_y ;
return *this;
}
void Print()
{
cout << "(" << m_x << " " << m_y << ")" << endl;
}
private:
int m_x;
int m_y;
};
//Point& operator++(Point& p)
//{
// ++p.m_x;
// ++p.m_y;
// return p;
//}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
++++A;
A.Print();//(3 2)
return 0;
}
++(右)
- 说明:++(右)不能进行连+
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point
{
// friend const Point operator++(Point& p, int);
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
const Point operator++(int) //因为不能连+的,所以加个const
{
Point tmp = *this;
m_x++;
m_y++;
return tmp;
}
void Print()
{
cout << "(" << m_x << " " << m_y << ")" << endl;
}
private:
int m_x;
int m_y;
};
//const Point operator++(Point& p, int) //返回的是临时变量,所以不能返回引用
//{
// Point tmp = p;
// p.m_x++;
// p.m_y++;
// return tmp;
//}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
A++;
A.Print(); //(2 1)
return 0;
}
双目操作符重载
- 重载写法两种:
operator+(L,R) //全局
L.operator+(R) //成员函数
+ 运算符
- 举例:重载+操作符:将两个类相加(对应的成员变量相加)
写法1:全局函数,在类中申明为友元
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point
{
//friend Point operator+(Point& p1, Point& p2);
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
Point operator+(Point& p2) //定义为成员函数,禁止返回局部变量或者它的引用
{
Point tmp(this->m_x + p2.m_x, this->m_y + p2.m_y);
return tmp;
}
void Print()
{
cout << "(" << m_x << " " << m_y << ")" << endl;
}
private:
int m_x;
int m_y;
};
//Point operator+(Point& p1,Point& p2) //重载+操作符,在Point类里面申明为友元,禁止返回局部变量或者它的引用
//{
// Point tmp(p1.m_x + p2.m_x, p1.m_y + p2.m_y);
// return tmp;
//}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
Point C = A+B; //全局显式: operator+(A,B) //成员函数显式:A.operator+(B)
C.Print();
return 0;
}
+=运算符
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point
{
friend Point& operator+=(Point& p1, Point& p2); //申明全局为友元
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
//Point& operator+=(Point& p2) //或者申明成员函数
//{
// m_x += p2.m_x;
// m_y += p2.m_y;
// return *this;
// }
void Print()
{
cout << "(" << m_x << " " << m_y << ")" << endl;
}
private:
int m_x;
int m_y;
};
Point& operator+=(Point& p1, Point& p2)
{
p1.m_x += p2.m_x;
p1.m_y += p2.m_y;
return p1;
}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
(A+=B)+=B;
A.Print();
return 0;
}
<< >> 运算符
- 注意: >> 也不能写在成员函数内,只能写成全局函数
#include "stdafx.h"
#include <iostream>
#include "person.h"
using namespace std;
class Point
{
friend ostream& operator<<(ostream& os, Point& p);
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
// ostream& operator<<(ostream& os) <<操作符禁止写成员函数,否则调用变成: A << cout , 改变本意
// {
// os << "(" << m_x << " " << m_y << ")";
// return os;
//}
private:
int m_x;
int m_y;
};
ostream& operator<<(ostream& os, Point& p)
{
os << "(" << p.m_x << " " << p.m_y << ")" ;
return os;
}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
cout << A << B << endl;
return 0;
}
- 注意: >> 也不能写在成员函数内
#include "stdafx.h"
#include <iostream>
using namespace std;
class Point
{
friend istream& operator>>(istream& is, Point& p);
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
}
void Print()
{
cout << "(" << m_x << "," << m_y << ")" << endl;
}
private:
int m_x;
int m_y;
};
istream& operator>>(istream& is, Point& p)
{
cout << "a:";
is >> p.m_x;
cout << "b:";
is >> p.m_y;
return is;
}
int main(void)
{
Point A(1, 0);
Point B(2, 2);
cin >> A >> B;
A.Print();
B.Print();
return 0;
}
= 运算符
#include "stdafx.h"
#include <iostream>
#include <string.h>
using namespace std;
class Student
{
public:
Student() //无参构造
{
m_id = 0;
m_name = NULL;
}
Student(int id, const char name[]) //有参构造
{
m_id = id;
int length = strlen(name);
m_name = new char[length + 1];
strcpy_s(m_name,length+1,name);
}
Student(const Student& another) //拷贝构造
{
m_id = another.m_id;
int length = strlen(another.m_name);
m_name = new char[length + 1];
strcpy_s(m_name, length + 1, another.m_name);
}
Student& operator=(const Student& another) //=操作符重载,三件事
{
if(this==&another) return *this;//1. 防止自身赋值
m_id = another.m_id;
if (m_name != NULL) //2. 判断是否为空,不为空,先释放
{
delete[]m_name;
m_name = NULL;
}
int length = strlen(another.m_name); //3. 开辟内存
m_name = new char[length + 1];
strcpy_s(m_name, length + 1, another.m_name);
return *this;
}
void Print()
{
cout << m_name << ": " << m_id << endl;
}
~Student()
{
if (m_name != NULL)
{
delete[] m_name;
m_name = NULL;
}
}
private:
int m_id;
char* m_name;
};
int main(void)
{
Student A (1, "julian");
Student B (2, "mark");
Student C (3, "kerr");
C =A =B;
C.Print(); //mark: 2
return 0;
}
不建议重载 && 和 ||
- 在已有的运算结构中 &&和 || 都有短路现象:
if(a&&(a=1))
如果a是0,那么后面(a=1)应该不执行,结果还是0,但是当你重载&&的时候: object.operator&&(t1), t1作为参数传进去,肯定是执行的,所以不会发生短路现象,但是有时候需要重载又不关心短路现象的时候可以进行重载
( ) 的重载
- 重载()叫做仿函数,调用形式和函数类似
class Sqr
{
public:
Sqr(int a)
{
this->a = a;
}
//想把s对象 定义成一个 带有一个参数的函数, 求出平方返回
//此函数功能就是 对a求平方
int operator()(int a)
{
return a*a; //这个a和成员变量无关
}
private:
int a;
};
int main()
{
Sqr A(3); //定义Sqr的对象A
A(2); //求2的平方,返回4
}