函数重载
函数重载:在同一个class内,可以声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)不同,样例如下:
#include <iostream>
#include <string>
using namespace std;
class PrintLog {
public:
void printLog(int value) {
cout << "printLog(int value)" << endl;
}
void printLog(string str) {
cout << "printLog(string str)" << endl;
}
void printLog(int value, string str) {
cout << "printLog(int value, string str)" << endl;
}
};
int main(int argc, char const* argv[]) {
PrintLog pl;
pl.printLog(1);
pl.printLog("bengi");
pl.printLog(1, "bengi");
return 0;
}
输出如下:
printLog(int value)
printLog(string str)
printLog(int value, string str)
运算符重载
语法规则:operator
后面接需要重载的符号,例如+
运算符重载可以写为operator+
。
+ 算术运算符重载
需求:需要将两个class中的属性进行相加,将属性相加的结果赋值给新的class中的属性。可以使用全局函数进行重载,也可以用成员函数进行重载。
- 运用全局函数进行重载
#include <iostream>
#include <string>
using namespace std;
/* + 重载 */
class test {
public:
test() {}
test(int value) {
this->value = value;
}
public:
int value;
};
/* 全局函数重载+的思维流程:
1. 需求是t3 = t1 + t2; t3还是一个test类,所以返回值是test
2. 需要执行的是t1 + t2,所以需要将t1和t2两个类作为参数传入
3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参
4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
*/
test operator+(const test& t1, const test& t2) {
test t0;
t0.value = t1.value + t2.value;
return t0;
}
int main(int argc, char const* argv[]) {
test t1(10);
test t2(20);
test t3;
/* 需求:t3 = t1 + t2
结果:t3.value = t1.value + t2.value; //10 + 20 = 30;
*/
t3 = t1 + t2;
cout << "t3.value: " << t3.value << endl; /* 输出:30 */
return 0;
}
- 运用成员函数进行重载
#include <iostream>
#include <string>
using namespace std;
/* + 重载 */
class test {
public:
test() {}
test(int value) {
this->value = value;
}
public:
int value;
public:
/* 成员函数重载+的思维流程:
1. 需求是t3 = t1 + t2; t3还是一个test类,所以返回值是test
2. t1 + t2 = t1.operator+(t2),因为this指针的指向是被调用成员函数的所属对象,所以参数传入t2即可
3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参
4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
*/
test operator+(const test& t2) {
cout << this->value << endl; /* 输出的是t1.value = 10 */
test t0;
t0.value = this->value + t2.value;
return t0;
}
};
int main(int argc, char const* argv[]) {
test t1(10);
test t2(20);
test t3;
/* 需求:t3 = t1 + t2
结果:t3.value = t1.value + t2.value; //10 + 20 = 30;
*/
t3 = t1 + t2;
cout << "t3.value: " << t3.value << endl; /* 输出:30 */
return 0;
}
<< 左移运算符重载
#include <iostream>
#include <string>
using namespace std;
/* << 重载 */
class test {
public:
test(int value) {
this->value = value;
}
public:
int value;
};
/* 全局函数重载<<的思维流程:
1. 需求是cout << t1 << endl; 为了符合链式编程思想,有追加一个 << endl; 所以返回值需要定义为cout的类型ostream&(为何是引用,见3)
2. 需要执行的是cout << t1,所以讲cout和t1作为参数传入
3. 传入的参数不希望是重新拷贝出来的,保持一份数据,所以采用引用的方式传参。另外cout是标准输出流,也只能存在一份
4. 因为传入的是引用,所以为了避免被改动到,所以需要加const来修饰
5. 传入的参数cout前为何不加const,因为cout是标准输出流,本身没有加const修饰,如果硬加上会报错
*/
ostream& operator<<(ostream& cout, const test& t) {
cout << t.value;
return cout;
}
int main(int argc, char const* argv[]) {
test t1(10);
/* 需求:cout << t1 << endl;
结果:输出 t1.value = 10;
*/
cout << t1 << endl;
return 0;
}
注意:<<运算符只能通过全局函数进行重载,原因如下:
如果我们通过成员函数进行重写,那么cout << t1
实质上的代码等同于t1.operator<<(cout)
,将代码简写之后就变成了t1 << cout
,这就不符合cout << t1
的要求了,所以无法通过成员函数进行重写。
自增运算符重载
自增分成前置(++i
)和后置(i++
)
#include <iostream>
#include <string>
using namespace std;
/* i++和++i 重载 */
class test {
public:
test(int value) {
this->value = value;
}
/* 成员函数重载++i的思维流程:
1. 因为自增运算符是可以持续自增的,例如++(++i),所以返回值类型需要是原本的test class,即test&
3. 因为++i是先加后用,所以不需要任何临时数据来转接,直接++this->value即可
*/
test& operator++() {
++(this->value);
return *this;
}
/* 成员函数重载i++的思维流程:
1. 因为i++和++i都是使用的++,编译器为了区分两者,重载i++的时候,参数定义为operator++(int),加以区分
2. 因为i++是先用后加,所以需要转接一下,才可以实现先用后加
3. 因为i++是先用后加,用过之后再用就是++后的值了,所以不返回引用,直接返回值
*/
test operator++(int) { /* int是一个占位参数,用来区分i++和++i */
test temp = *this; /* 记录当前原本的值,然后让本身的值++,返回的是以前的值,从而实现先用后加的效果 */
this->value++;
return temp;
}
public:
int value;
};
int main(int argc, char const* argv[]) {
test t1(10);
test t2(20);
/* 需求1:++t1;
结果:++t1.value;
*/
++(++t1);
cout << t1.value << endl; /* 输出12 */
/* 需求1:t1++;
结果:t1.value++;
*/
test t3 = t2++;
cout << t2.value << endl; /* 输出21 */
cout << t3.value << endl; /* 输出20 t3=t2++; 这个可以实现是因为编译器默认帮我们进行了值拷贝 */
return 0;
}
= 赋值运算符重载
如果不实现=运算符重载,编译器会默认帮我们做值拷贝。
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test(int a, int b) {
this->a = a;
this->b = b;
}
public:
int a;
int b;
};
/* 重载<<运算符 */
ostream& operator<<(ostream& cout, const test& t) {
cout << t.a << " " << t.b;
return cout;
}
int main(int argc, char const* argv[]) {
test t1(1, 2);
test t2 = t1; /* 不实现=运算符,编译器会默认帮我们做值拷贝 */
cout << t1 << endl; /* 输出1 2 */
cout << t2 << endl; /* 输出1 2 */
return 0;
}
但是如果出现指针相关的,如果只进行值拷贝,会导致可能出现重复释放问题,所以需要重载,做到深拷贝,如下:
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test(int a, int b, int c) {
this->a = a;
this->b = b;
this->c = new int(c);
}
~test() {
if (this->c != NULL) {
delete this->c;
this->c = NULL;
}
}
test& operator=(test& t) {
cout << "opertor=" << endl;
this->a = t.a;
this->b = t.b;
if (this->c != NULL) {
delete this->c;
this->c = NULL;
}
this->c = new int(*t.c);
return *this;
}
public:
int a;
int b;
int* c;
};
/* 重载<<运算符 */
ostream& operator<<(ostream& cout, const test& t) {
cout << t.a << " " << t.b << " " << *t.c;
return cout;
}
int main(int argc, char const* argv[]) {
test t1(1, 2, 3);
test t2(2, 3, 4);
t2 = t1; /* 相当于执行 t2.operator=(t1) */
cout << "t2 = t1" << endl;
/* PS:如果用下面的方式,不会调用到重载的?? */
test t3 = t1;
cout << t1 << endl; /* 输出1 2 3*/
cout << t2 << endl; /* 输出1 2 3*/
cout << t3 << endl; /* 输出1 2 3*/
return 0;
}
==/> 关系运算符重载
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test(int a, int b) {
this->a = a;
this->b = b;
}
bool operator==(const test& t) {
if (this->a == t.a && this->b == t.b) {
return true;
} else {
return false;
}
}
bool operator>(const test& t) {
int t1 = this->a + this->b;
int t2 = t.a + t.b;
if (t1 > t2) {
return true;
} else {
return false;
}
}
int a;
int b;
};
int main(int argc, const char** argv) {
test t1(10, 10);
test t2(10, 11);
test t3(10, 10);
/* 需求1:判断t1和t2是否相等,判断t1和t3是否相等。相等的条件是t1.a == t2.a && t1.b == t2.b
*/
if (t1 == t2) {
cout << "t1 == t2" << endl;
} else {
cout << "t1 != t2" << endl; /* 输出这句 */
}
if (t1 == t3) {
cout << "t1 == t3" << endl; /* 输出这句 */
} else {
cout << "t1 != t3" << endl;
}
/* 需求2:判断t1和t2哪个更大,条件是t1.a+t1.b > t2.a+t2.b 则输出更大 */
if (t1 > t2) {
cout << "t1 > t2" << endl;
} else {
cout << "t1 <= t2" << endl; /* 输出这句 */
}
return 0;
}
() 函数调用运算符重载
重载()后因为非常类似函数,所以被称为仿函数
#include <iostream>
#include <string>
using namespace std;
class test {
public:
void operator()(int value) {
cout << "print value: " << value << endl;
}
};
int main(int argc, const char** argv) {
test t;
t(10); /* 输出:print value: 10 */
test()(20); /* 匿名对象调用,输出:print value: 20 */
return 0;
}
运算符重载+函数重载
#include <iostream>
#include <string>
using namespace std;
class test {
public:
test(int a, int b) {
this->a = a;
this->b = b;
}
/* 两个class之间相加 */
test operator+(test& t) {
test temp(0, 0);
temp.a = this->a + t.a;
temp.b = this->b + t.b;
return temp;
}
test operator+(int value) {
test temp(0, 0);
temp.a = this->a + value;
temp.b = this->b;
return temp;
}
int a;
int b;
};
/* 实现<<重载 */
ostream& operator<<(ostream& cout, const test& t) {
cout << t.a << " " << t.b;
return cout;
}
int main(int argc, const char** argv) {
test t1(1, 2);
test t2(1, 1);
test t3 = t1 + t2; /* t1.operator+(t2) */
test t4 = t1 + 10; /* t1.operator+(10) */
cout << t1 << endl; /* 输出:1 2 */
cout << t3 << endl; /* 输出:2 3 */
cout << t4 << endl; /* 输出:11 2 */
return 0;
}