1、简介
对于默认类型如int、float等,都具有 + - * / << ++ -- 等运算方法可以使用,而对于用户自定义的类或结构体没有这些运算方法,需要用户自己通过运算符重载的方式生成。
2、加法
默认使用 operator+ 为函数名,可以在调用时直接使用 a + b的形式
2.1类中的加法运算符重载 + - * /
如下例中,operator+成员函数
class Garage {
public:
float box_num;
float sum_weight;
Garage(float num, float weight) {
this->box_num = num;
this->sum_weight = weight;
}
Garage operator+(Garage& g2) {
Garage temp(0,0);
temp.box_num = this->box_num + g2.box_num;
temp.sum_weight = this->sum_weight + g2.sum_weight;
return temp;
}
void print() {
cout << "box_num:" << box_num << ",";
cout << "sum_weight:" << sum_weight << endl;;
}
};
2.2全局函数的加法运算符重载
Garage operator+(Garage& g1, Garage& g2) {
Garage temp(0, 0);
temp.box_num = g1.box_num + g2.box_num;
temp.sum_weight = g1.sum_weight + g2.sum_weight;
return temp;
}
2.3 运算符重载函数的重载
Garage operator+(Garage& g1, float num) {
Garage temp(0, 0);
temp.box_num = g1.box_num + num;
temp.sum_weight = g1.sum_weight + num;
return temp;
}
Garage operator+(Garage& g1, Garage& g2) {
Garage temp(0, 0);
temp.box_num = g1.box_num + g2.box_num;
temp.sum_weight = g1.sum_weight + g2.sum_weight;
return temp;
}
3、左移运算符重载 <<
3.1 注意点
a、cout 类型为 ostream类型,只能有一个,因此需要在运算符重载时定义为引用形式&。
b、在运算符重载时需要返回 ostream的引用类型,防止后续还需要输出别的如endl等。
c、左移运算符重载要使用简便输出,就只能定义为全局函数,且需要在类中定义为友元。
3.2 示例
class Garage {
friend ostream& operator<<(ostream& out, Garage& g1);
public:
Garage(float num, float weight) {
this->box_num = num;
this->sum_weight = weight;
}
private:
float box_num;
float sum_weight;
};
ostream& operator<<(ostream& out, Garage& g1) {
cout << "box_num:" << g1.box_num << " ,sum_weight :" << g1.sum_weight << endl;
return out;
}
int main() {
Garage g1(2,10);
cout << g1 << endl;
system("pause");
return 0;
}
4、++运算符重载
4.1 注意点
a、前置++,需要采取函数引用形式,来返回已经自加过的值。
b、后置++,为了防止函数重载,需要加入一个int作为占位,且不用函数引用,使得函数在自加前先返回,再自加。
4.2 示例
如下示例同样使用了3节中的左移运算符重载:
class Man {
friend ostream& operator<<(ostream& out, Man m);
public:
Man(int age) {
this->age = age;
}
//前置++,需要采取函数引用形式,来返回已经自加过的值
Man& operator++() {
this->age++;
return *this;
}
//后置++,为了防止函数重载,需要加入一个int作为占位,且不用函数引用,使得函数在自加前先返回,再自加
Man operator++(int) {
Man temp(this->age);
temp.age = this->age++;//先返回,再自加
return temp;
}
private:
int age;
};
ostream& operator<<(ostream& out, Man m) {
cout << "age:" << m.age << endl;
return out;
}
int main() {
Man m1(10);
cout << ++m1 << endl;
cout << m1++ << endl;
cout << m1 << endl;
system("pause");
return 0;
}
输出:
5、赋值运算符重载 =
5.1 拷贝概念
a、浅拷贝,只是简单更改了指向。
b、深拷贝,先判断当前对象是否有堆区内存,有则先释放内存,再进行空间开辟,存放数据。
5.2 注意
在赋值运算符重载中使用浅拷贝,会在添加了释放内存的析构函数中报错,应该使用深拷贝。
原因:因为浅拷贝只是简单的将对象内存指针都指向了 存储数据的那个堆区部分 ,并没有在堆区开辟新的内存,导致程序在将要结束前,析构函数对同一个 内存区域进行了多次的内存释放。
5.3 示例
class Man {
public:
Man(int age) {
this->m_aGe =new int(age);
}
~Man() {//如果有指向,则将堆区内存释放
if (*m_aGe != NULL) {
delete this->m_aGe;
m_aGe = NULL;
}
}
Man& operator=(Man& m) {
//浅拷贝,只是简单更改了指向
//this->m_aGe = m.m_aGe;
//深拷贝,先判断当前对象是否有堆区,有则先释放,再进行拷贝
if (this->m_aGe != NULL) {
m_aGe = NULL;
delete this->m_aGe;
}
this->m_aGe = new int(*m.m_aGe);
return *this;
}
void print() {
cout << "m_aGe: "<< *(this->m_aGe)<<", 地址 :" << this->m_aGe << endl;
}
private:
int * m_aGe;
};
int main() {
Man m1(10);
Man m2(20);
Man m3(30);
m3 = m2 = m1;
m1.print();
m2.print();
m3.print();
system("pause");
return 0;
}
6 、关系运算符重载 < > == !=
6.1 示例
class Man {
public:
Man(int age) {
this->m_aGe =new int(age);
}
bool operator==(Man& m) {
if (*m.m_aGe == *this->m_aGe) {
return true;
}
else
return false;
}
bool operator!=(Man& m) {
if (*m.m_aGe == *this->m_aGe) {
return false;
}
else
return true;
}
private:
int * m_aGe;
};
int main() {
Man m1(10);
Man m2(120);
if (m1 == m2) {
cout << "m1 = m2" << endl;
}
else
cout << "m1 != m2" << endl;
if (m1 != m2) {
cout << "m1 != m2" << endl;
}
else
cout << "m1 = m2" << endl;
system("pause");
return 0;
}
7、函数调用运算符重载 ()
由于函数调用运算符重载 () 与函数的调用非常相似,因此这种方法也被称为仿函数。
示例:
class Man {
public:
void operator()(string str){
cout << "you said : " << str << endl;
}
int operator()(int a, int b) {
cout << " you used the add methoed ,result is :" << a + b << endl;
return a + b;
}
};
int main() {
Man m1;
m1("this man's age are 10");
//匿名对象调用,当前行运行完了就释放
Man()("abcdefg");
int add_r = m1(2, 3);
system("pause");
return 0;
}