C++梁哥笔记day11 | 我的日常分享

C++梁哥笔记day11

类与对象

一、运算符重载

运算符重载,就是对已有的运算符进行重新定义,赋予另一种功能,以适应不同的数据类型。

运算符重载只是一种“语法上的方便”,也就是它只是另一种函数调用的方式。
在C++中,可以定义一个处理类的新运算符。这种定义很像一个普通的函数定义,只是函数的名字由关键字operator及其紧跟的运算符组成。差别仅此而已。它像任何其他很熟一样也是一个函数,当编译器遇到适合的模式时,就会调用这个函数。
语法:定义重载的运算符就像定义函数,只是改函数的名字是operator@,这里的@代表了被重载函数的运算符。函数参数中参数个数取决于两个因素。运算符是一元(一个参数)的还是二元(两个参数);运算符被定义为全局函数(对于一元是一个参数,对于二元是两个参数)还是成员函数(对与一元没有参数,对于二元是一个参数,此时该类的对象用作左耳参数)

【两个极端】有些人很容易滥用运算符重载,它确实是一个有趣的工具,但是应该注意,它仅仅是一种语法上的方便而已,是另外一种函数调用的方式。从这个角度来看,只有在能使涉及类的代码更易写,尤其是读时(请记住,读代码的机会比我们写代码多多了)才有理由重载运算符。如果不是这样,就改用其他更易用、更易读的方式,对于运算符重载,另外一个常见的反应就是恐慌:突然之间,C运算符的含义变得不同寻常了,一切都变了,所有C代码的功能都要改变!并非如此,对于内置的数据类型的表达式的运算符是不可能改变的。(例如想重载int类型数据的+号)

  • 重载双左尖括号<<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Person{
friend ostream& operator<<(ostream &out,Person ob);
private:
char *name;
int age;
public:
Person(){
cout<<"无参构造"<<endl;
}
Person(char *name,int age){
cout<<"有参构造"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name,name);
this->age = age;
}
~Person(){
cout<<"析构函数"<<endl;
if(this->name != NULL){
delete [] this->name;
}
}
Person(const Person &ob){
cout<<"拷贝构造函数"<<endl;
this->age = ob.age;
this->name = new char[strlen(name)+1];
strcpy(this->name,ob.name);
}
void showPerson(){
cout<<"name:"<<this->name<<",age:"<<this->age<<endl;
}
};
ostream& operator<<(ostream &out,Person ob){
out<<"name:"<<ob.name<<",age:"<<ob.age<<endl;
return out;
}

void test01(){
Person ob1("lucy",18);
ob1.showPerson();
//operator<<(cout,ob1);直接将其看做一个函数也是可以的,但是这样比较麻烦
Person ob2("bob",20);
cout<<ob1<<ob2<<endl;
}

运行结果:
图片

注意点:

  1. 这个函数重载函数为全局函数,要使用Person类中的私有的成员,需要将这个函数设置为Person类的友类。
  2. 要实现out<<ob1<<ob2<<endl;后面还要连接其他的,需要返回值设置为out。
  • 全局友元函数实现重载加法运算符+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <cstring>
using namespace std;
class Person{
friend ostream& operator<<(ostream &out,Person ob);
friend Person operator+(Person &ob1,Person &ob2);
private:
char *name;
int age;
public:
Person(){
cout<<"无参构造"<<endl;
}
Person(char *name,int age){
cout<<"有参构造"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name,name);
this->age = age;
}
~Person(){
cout<<"析构函数"<<endl;
if(this->name != NULL){
delete [] this->name;
}
}
Person(const Person &ob){
cout<<"拷贝构造函数"<<endl;
this->age = ob.age;
this->name = new char[strlen(name)+1];
strcpy(this->name,ob.name);
}
void showPerson(){
cout<<"name:"<<this->name<<",age:"<<this->age<<endl;
}
};
ostream& operator<<(ostream &out,Person ob){
out<<"name:"<<ob.name<<",age:"<<ob.age<<endl;
return out;
}
Person operator+(Person &ob1,Person &ob2){
//1、拼接name
char *tmp_name = new char[strlen(ob1.name) + strlen(ob2.name) + 1];
strcpy(tmp_name,ob1.name);
strcat(tmp_name,ob2.name);
//2、age相加
int tmp_age = ob1.age + ob2.age;
Person ob3 = Person(tmp_name,tmp_age);
return ob3;
}
void test01(){
Person ob1("lucy",18);
ob1.showPerson();
Person ob2("bob",20);
cout<<ob1<<ob2<<endl;
}
void test02(){
Person ob1("lucy",18);
Person ob2("bob",20);
Person ob3 = ob1+ob2;
cout<<ob3;
cout<<(ob1+ob2);
//cout<<operator+(ob1,ob2);//出现段错误 不知道原因
Person ob4 = operator +(ob1,ob2);
ob4.showPerson();
//cout<<ob4;//出现段错误 不知道原因

}

int main(int argc, char *argv[])
{
test02();
return 0;
}

运行结果:
图片

注意点:

  1. 这个operator +函数重载函数为全局函数,要使用Person类中的私有的成员,需要将这个函数设置为Person类的友类。
  2. 思考:要实现多个(超过两个)对象相加如何实现?
  • 成员函数实现重载加法运算符+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <cstring>
using namespace std;
class Person{
friend ostream& operator<<(ostream &out,Person ob);
private:
char *name;
int age;
public:
Person operator+(Person &ob){
//1、拼接name
char *tmp_name = new char[strlen(this->name) + strlen(ob.name) + 1];
strcpy(tmp_name,this->name);
strcat(tmp_name,ob.name);
//2、age相加
int tmp_age = this->age + ob.age;
Person ob3 = Person(tmp_name,tmp_age);
return ob3;
}
Person(){
cout<<"无参构造"<<endl;
}
Person(char *name,int age){
cout<<"有参构造"<<endl;
this->name = new char[strlen(name)+1];
strcpy(this->name,name);
this->age = age;
}
~Person(){
cout<<"析构函数"<<endl;
if(this->name != NULL){
delete [] this->name;
}
}
Person(const Person &ob){
cout<<"拷贝构造函数"<<endl;
this->age = ob.age;
this->name = new char[strlen(name)+1];
strcpy(this->name,ob.name);
}
void showPerson(){
cout<<"name:"<<this->name<<",age:"<<this->age<<endl;
}
};
ostream& operator<<(ostream &out,Person ob){
out<<"name:"<<ob.name<<",age:"<<ob.age<<endl;
return out;
}

void test01(){
Person ob1("lucy",18);
ob1.showPerson();
Person ob2("bob",20);
cout<<ob1<<ob2<<endl;
}
void test02(){
Person ob1("lucy",18);
Person ob2("bob",20);
Person ob3 = ob1.operator +(ob2);
cout<<ob3;
Person ob4 = ob1 + ob2;
cout<<ob4;
}

int main(int argc, char *argv[])
{
test02();
return 0;
}

运行结果:
图片

注意点:

  1. 成员函数实现运算符重载其一个参数利用this指针代替了
  2. 调用方式与全局函数实现运算符重载完全一致