C++运算符重载
-
运算符重载
-
运算符重载的作用
-
运算符重载入门
-
运算符重载的限制
-
运算符重载基础
-
运算符重载的方法步骤
-
重载++ 需要注意(重点)
-
友元函数 重载 << 还有链式编程
-
简单版的复数类重载
-
简单的name类重载
-
编写复数类
-
main.cpp
- Complex.h
- Complex.cpp
-
编写string类
-
main.cpp
- MyString.h
- MyString.cpp
运算符重载
什么是运算符重载?
运算符重载的本质是一个函数
运算符重载的作用
为什么会用运算符重载机制?
用复数类举例
Complex c3 = c1 + c2;
原因 Complex是用户自定义类型,编译器根本不知道如何进行加减
编译器给提供了一种机制,让用户自己去完成,自定义类型的加减操作。。。。。
这个机制就是运算符重载机制
运算符重载入门
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 1#include <iostream>
2using namespace std;
3class Complax
4{
5public:
6 Complax(int a = 0, int b = 0)
7 {
8 this->a = a;
9 this->b = b;
10 }
11 void printC()
12 {
13 cout << "a = " << a << "\tb = " << b << endl;
14 }
15 ~Complax() {}
16//private:
17public:
18 int a;
19 int b;
20};
21// 1定义全局函数
22Complax myAdd(Complax &c1, Complax &c2)
23{
24 Complax temp(c1.a + c2.a, c1.b + c2.b);
25 return temp;
26}
27// 2函数名升级
28Complax operator+(Complax &c1, Complax &c2)
29{
30 Complax temp(c1.a + c2.a, c1.b + c2.b);
31 return temp;
32}
33int main01()
34{
35 int a = 0, b = 0;
36 int c; // 基础性数据类型,编译器已经知道了,如何运算
37 c = a + b;
38 // a + bi; // 复数运算规则
39 Complax c1(1, 2), c2(3, 4);
40 Complax c3; // 2c3是用户自定义数据类型,c++编译器不知道如何运算
41// c3 = c1 + c2;
42 // 3c++编译器应该给我们提供一种机制
43 // 让自定义数据类型 有机会进行 运算符操作 ==> 运算符重载
44 // 4运算符重载机制
45 Complax c4 = myAdd(c1, c2);
46 c4.printC();
47 // 步骤二:Complax c4 = c1+c2;
48 // Complax c5 = operator+(c1, c2);
49 // c5.printC();
50 // 步骤三:
51 Complax c5 = c1 + c2;
52 c5.printC();
53 // 运算符重载的本质 是 函数调用
54 return 0;
55}
56
57
运算符重载的限制
运算符重载基础
运算符重载的方法步骤
全局函数、类成员函数方法实现运算符重载步骤
-
要承认操作符重载是一个函数,写出函数名称operator+ ()
-
根据操作数,写出函数参数
-
根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务
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 1#include <iostream>
2using namespace std;
3
4class Complax
5{
6private:
7 int a;
8 int b;
9 // 重载友元函数 全局函数 操作符重载
10 friend Complax operator+(Complax &c1, Complax &c2);
11public:
12 Complax(int a = 0, int b = 0)
13 {
14 this->a = a;
15 this->b = b;
16 }
17 void printC()
18 {
19 cout << "a = " << a << "\tb = " << b << endl;
20 }
21 // 2成员函数法 实现 - 运算符重载
22 Complax operator-(Complax &c2)
23 {
24// this->a -= c2.a;
25// this->b -= c2.b;
26// return *this; // 这一个会改变c1的值,因为是+=
27 Complax temp(this->a - c2.a, this->b -c2.b);
28 return temp;
29
30 }
31
32};
33// 1全局函数法 实现 + 运算符重载
34Complax operator+(Complax &c1, Complax &c2)
35{
36 Complax temp(c1.a+c2.a, c1.b+c2.b);
37 return temp;
38}
39/*
40 全局函数,类成员函数方法实现运算符重载步骤
41 1:要承认运算符重载是一个函数, 写出函数名称
42 2: 根据操作数,写出函数参数
43 3:根据业务,完善函数的返回值(看函数返回引用,元素,指针),及实现函数业务
44*/
45int main()
46{
47 Complax c1(1, 2), c2(3, 4);
48
49 // 1全局函数法 实现 - 运算符重载
50 // Complax operator+(Complax &c1, Complax &c2)
51 Complax c3 = c1 + c2;
52 c3.printC();
53
54 // 2成员函数法 实现 - 运算符重载
55 // Complax operator-(Complax &c2);
56 Complax c4 = c1 - c2;
57 c4.printC();
58
59 return 0;
60}
61
62
重载++ 需要注意(重点)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 1#include <iostream>
2using namespace std;
3class Complax
4{
5private:
6 int a;
7 int b;
8 // 1全局函数法 实现 ++ 运算符重载
9 friend Complax& operator++(Complax &c1); // 这里是返回一个引用注意,前置++
10 friend Complax operator++(Complax &c2, int); // 后置++
11
12public:
13 Complax(int a = 0, int b = 0)
14 {
15 this->a = a;
16 this->b = b;
17 }
18
19 // 前置--
20 // 因为前置返回的是本身,所以返回一个引用
21 // Complax& operator--(Complax &c1) 这个是写错的,注意错在哪里
22 Complax& operator--()
23 {
24 this->a --;
25 this->b --;
26 return *this;
27 }
28
29 // 后置-- 因为后置返回的是一个副本所以不用 返回引用
30 Complax operator--(int)
31 {
32 Complax tem = *this;
33 this->a--;
34 this->b--;
35 return tem;
36 }
37
38 void printC()
39 {
40 cout << "a = " << a << "\tb = " << b << endl;
41 }
42};
43
44
45
46// 特别注意 只有成员函数才有 this指针
47// 1全局函数法 实现 前置++ 运算符重载
48Complax& operator++(Complax &c1)
49{
50 c1.a++;
51 c1.b++;
52 return c1;
53}
54// 后置++
55Complax operator++(Complax &c2, int) // int防止与前置++重载而加的占位符
56{
57 // 因为后置++是使用, 在让c2++所以要定义一个临时变量
58 Complax tem = c2;
59 c2.a++;
60 c2.b++;
61 return tem;
62}
63
64
65int main()
66{
67 Complax c1(1, 2), c2(30, 40);
68
69 // 1全局函数法 实现 前置++ 运算符重载
70 // Complax& operator++(Complax &c1);
71 ++c1; // 相当于 operator++(c1);
72 c1.printC();
73
74 // 2成员函数 实现 前置-- 运算符重载
75 // 相当于c2.operator--();
76 --c2;
77 c2.printC();
78
79 // 1全局函数法 实现 后置++ 运算符重载
80 // operator++(c2);
81 c2++;
82 // Complax& operator++(Complax &c1); 前置++
83 // Complax operator++(Complax &c2, int); // int防止与前置++重载而加的占位符
84 c2.printC();
85
86 // 2成员函数 实现 后置-- 运算符重载
87 // 相当于c2.operator--();
88 // Complax operator--(int) 函数原型
89 c1--;
90 c1.printC();
91
92 return 0;
93}
94
95
友元函数 重载 << 还有链式编程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1//a)用全局函数方法实现 << 操作符
2ostream& operator<<(ostream &out, Complex &c1)
3{
4 //out<<"12345,生活真是苦"<<endl;
5 out<<c1.a<<" + "<<c1.b<<"i "<<endl;
6 return out;
7}
8//调用方法
9cout<<c1;
10//链式编程支持
11cout<<c1<<"abcc";
12//cout.operator<<(c1).operator<<("abcd");
13//函数返回值充当左值 需要返回一个引用
14b)类成员函数方法无法实现 << 操作符重载
15//因拿到cout这个类的源码
16//cout.operator<<(c1);
17
18
注意点
友员函数重载运算符常用于运算符的左右操作数类型不同的情况
在第一个参数需要隐式转换的情形下,使用友员函数重载运算符是正确的选择
友员函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
C++中不能用友员函数重载的运算符有
1
2
3 1= () [] ->
2
3
所以这个可以在写一个operator + 或者写一个友元函数重载
简单版的复数类重载
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 1#include <iostream>
2
3using namespace std;
4
5class Complax
6{
7private:
8 int a;
9 int b;
10 friend ostream& operator<<(ostream &out, const Complax &c1);
11public:
12 Complax(int a = 0, int b = 0)
13 {
14 this->a = a;
15 this->b = b;
16 }
17 // +运算符重载
18 Complax operator+(Complax &c2)
19 {
20 Complax tem(this->a + c2.a, this->b + c2.b);
21 return tem;
22 }
23 // -运算符重载
24 Complax operator-(Complax &rhl)
25 {
26 Complax tem(this->a - rhl.a, this->b - rhl.b);
27 return tem;
28 }
29 // 前置--
30 Complax& operator--()
31 {
32 this->a --;
33 this->b --;
34 return *this;
35 }
36 // 前置++
37 Complax& operator++()
38 {
39 this->a++;
40 this->b++;
41 return *this;
42 }
43
44 // 后置-- 因为后置返回的是一个副本所以不用 返回引用
45 Complax operator--(int)
46 {
47 Complax tem = *this;
48 this->a--;
49 this->b--;
50 return tem;
51 }
52 // 后置++
53 Complax operator++(int)
54 {
55 Complax tem = *this;
56 this->a++;
57 this->b++;
58 return tem;
59 }
60 void printC()
61 {
62 cout << "a = " << a << "\tb = " << b << endl;
63 }
64};
65
66
67// 这里的ostream 不能加const
68ostream& operator<<(ostream &out, const Complax &c1)
69{
70 cout <<"重载<<运算符 链式输出";
71 out << "c1.a = " << c1.a << "\t c1.b = " << c1.b << endl;
72}
73// 在<< 和 >> 运算符重载时 只能使用全局函数就是 加个友元声明
74int main32()
75{
76 Complax c1(1, 2), c2(30, 40);
77 int a = 10;
78 cout << a << endl; // 基本数据类型
79
80 // 自定义数据类型
81 cout << c1;
82 // 全局函数调用方法
83 // operator<<(cout ,c1);
84 // 函数类型声明
85 // friend void operator<<(const ostream &out, const Complax &c1);
86
87 cout << c2;
88 // 成员函数调用方法 在ostream类中添加 成员函数 operator<<
89 // 但是ostream类的源码拿不到,所以在这种情况下只能使用友元函数
90 // cout.operator<<(c2);
91
92
93 // 最好都写这一个
94 cout <<c1 << "sflkasdf";
95 // cout.operator<< (c1).operator<<("slkfdkls");
96 // 上式等价于 void.operator<<"slkfdls"; 所以
97 // 如果链式输入的话
98 // 就要把返回时改为ostroam &;
99
100
101
102 return 0;
103}
104int main031()
105{
106 Complax c1(1, 2), c2(30, 40);
107 // 后置++
108 c1++;
109 c1.printC();
110 // 前置++
111 ++c2;
112 c2.printC(); // 虽然最后结果显示都是一样的,但是调用的不一样,
113 // 因为printC函数输入的是前置,或后置之后的结果所以会输出相同
114
115 //+运算符重载
116 Complax c3 = c1 + c2;
117 c3.printC();
118
119 // -运算符重载
120 Complax c4 = c3 - c1;
121 c4.printC();
122
123 cout << "Hello world!" << endl;
124 return 0;
125}
126
127
简单的name类重载
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 1#include <iostream>
2#include <cstring>
3#include <cstdlib>
4using namespace std;
5
6class Name
7{
8public:
9 Name (const char *mp)
10 {
11 len = strlen(mp);
12 p = (char *)malloc(sizeof(len+1)); // 注意细节
13 strcpy(p, mp);
14 }
15
16 //Name obj2 = obj1;
17 // 解决方案:手工编写拷贝构造函数,使用深拷贝
18 Name (const Name &obj1)
19 {
20 len = obj1.len;
21 p = (char *)malloc(sizeof(len+1));
22 strcpy(p, obj1.p);
23 }
24
25 // 成员函数 =运算符重载 不能写全局函数
26 Name& operator=(const Name &obj)
27 {
28 // 先释放旧的内存 特别注意
29 if(p != NULL)
30 {
31 delete []p;
32 len = 0;
33 }
34 len = obj.len;
35 p = new char[len+1];
36 strcpy(p, obj.p);
37 return *this;
38 }
39 ~Name ()
40 {
41 cout << "\t析构函数" << endl;
42 if (p != NULL)
43 {
44 free(p);
45 p = NULL;
46 len = 0;
47 }
48 }
49 void printName()
50 {
51 cout <<"\tp = " << this->p << "\t len = " << this->len << endl;
52 }
53private:
54 char *p;
55 int len;
56};
57
58
59// 对象析构的时候会出现,错误
60// 调试存在bug
61// 析构的时候会出现二次释放
62//默认的拷贝构造函数,如果要对指针进行拷贝,则只是浅拷贝,拷贝过后是两个变量指向
63//同一段内存,释放拷贝的obj2后,obj1的指针就是垃圾值,在释放就会出错
64
65void objmain()
66{
67 Name obj1("aaaa");
68 Name obj2 = obj1;
69 Name obj3("sfs");
70
71 // obj3 = obj1; // 等号操作 c++编译器会对=进行默认的重载(同样会发生二次释放的问题)
72 // 就需要手动的写 operator= 函数
73
74 cout << "成员函数=重载 ";
75 obj3 = obj1;
76 obj3.printName();
77 // obj3.operator=(const Name & obj1);
78 // void operator=(const Name &obj) // 函数声明
79 // 如果要执行 obj3 = obj2 = obj1; 就需要把void 改成 Name&
80 {
81 obj3 = obj2 = obj1;
82 obj3.printName();
83 obj2.printName();
84 obj1.printName();
85 }
86
87}
88
89int main04()
90{
91 objmain();
92}
93
94// 重载 = 运算符注意点
95// 1 先把旧的内存释放
96// 2 返回一个引用 obj3 = obj1 = obj2;
97// 3数据进行拷贝
98
99
编写复数类
main.cpp
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 1#include <iostream>
2//#include "Complex.h"
3#include "Complex.cpp"
4using namespace std;
5// 需要注意的是 如果是在main中包含complex.cpp的话,就要在complex.cpp的函数
6// 写成内联函数, 并且在其中写上#include"Complex.h" 推荐
7// 或者在main中包含#include"Complex.h", 然后再complex.h中包含#include"Complex.cpp"
8
9// Complex类
10int main() {
11 std::cout << "Hello, World!" << std::endl;
12 Complex c(2, 3);
13 Complex c2(3, 4);
14 c += c2;
15 c -= c2;
16 Complex c3 = c2; // 调用拷贝构造函数
17 c3 = c; // 运算符重载
18 cout << c3 << endl;
19 Complex c4 = c + c2;
20 c2++;
21 cout << c << c2 << endl;
22 c == c2;
23 cout << sizeof(c)<<endl; // 16个字节
24
25// cout << c.real() << "i+"<< c.imge() << endl;
26
27 return 0;
28}
29
30
Complex.h
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 1//
2// Created by lk on 18-5-28.
3//
4
5#ifndef HOUJIE_COMPLEX_H // 防卫式声明
6#define HOUJIE_COMPLEX_H
7
8#include <iostream>
9
10class Complex {
11public:
12
13 Complex(double re = 0, double im = 0)
14 : re(re), im(im) {}
15
16 // 拷贝构造函数
17 Complex(const Complex &obj)
18 : re(obj.re), im(obj.im) {}
19
20 Complex operator+(const Complex &obj);
21
22 Complex operator-(const Complex &obj);
23
24 Complex &operator+=(const Complex &obj);
25
26 Complex &operator-=(const Complex &obj);
27
28 bool operator==(const Complex &obj);
29
30 Complex &operator--();
31
32 Complex &operator++();
33
34 Complex operator--(int);
35
36 Complex operator++(int);
37
38
39 double real() { return re; }
40
41 double imge() { return im; }
42
43private:
44 double re;
45 double im;
46
47 friend std::ostream &operator<<(std::ostream &os, Complex &obj);
48
49};
50
51
52#endif //HOUJIE_COMPLEX_H
53
54
Complex.cpp
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
74
75
76
77
78
79
80
81 1// Created by lk on 18-5-28.
2//
3
4#include "Complex.h"
5#include <iostream>
6inline
7Complex &Complex::operator+=(const Complex &obj) {
8 this->re += obj.re;
9 this->im += obj.im;
10 return *this;
11}
12inline
13Complex &Complex::operator-=(const Complex &obj) {
14 this->im -= obj.im;
15 this->re -= obj.re;
16 return *this;
17}
18
19// 前置-- --c
20inline
21Complex &Complex::operator--() {
22 this->im--;
23 this->re--;
24 return *this;
25}
26
27// 前置++ ++c
28inline
29Complex &Complex::operator++() {
30 this->im++;
31 this->re++;
32 return *this;
33}
34
35// 后置-- 因为后置返回的是一个副本所以不用返回引用 c--
36inline
37Complex Complex::operator--(int) {
38 Complex tem = *this;
39 this->im--;
40 this->re--;
41 return tem;
42}
43
44// 后置++ c++
45inline
46Complex Complex::operator++(int) {
47 Complex tem = *this;
48 this->im++;
49 this->re++;
50 return tem;
51}
52
53// 重载+ 调用者 c+c2
54// 这是类内函数, 用一个参数, 如果是类外的就要用两个参数
55inline
56Complex Complex::operator+(const Complex &obj) {
57 return Complex(this->im + obj.im, this->re + obj.re);
58}
59
60
61// 重载- 调用者 c-c2
62inline
63Complex Complex::operator-(const Complex &obj) {
64 Complex tem(this->im - obj.im, this->re - obj.re);
65 return tem;
66}
67
68// 重载 == c == c2
69inline
70bool Complex::operator==(const Complex &obj) {
71 return (this->im == obj.im && this->re == obj.re);
72}
73
74// 重载<< cout << c
75inline
76std::ostream &
77operator<<(std::ostream &os, Complex &obj) {
78 return os << obj.re << obj.im;
79}
80
81
编写string类
main.cpp
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 1 #if 0
2#include <iostream>
3//#include "MyString.h"
4#include "MyString.cpp"
5using namespace std;
6
7int main()
8{
9 MyString s("aaa");
10 MyString s2(10);
11 s2 = s;
12 cout << s << s2 << endl;
13 if (s == s2)
14 {
15 cout << "s == s2" << endl;
16 }
17 else
18 cout << "s != s2 "<< endl;
19 if (s == "aab")
20 cout << "s == aab" << endl;
21 if (s != "aab")
22 cout << "s != aab" << endl;
23 s2 = "abbb00";
24 auto t = s > "abb00";
25 cout << t << endl;
26 cout << s[2] << endl;
27// cin >> s;
28// cout << s;
29 MyString s3 = "sjkf";
30 s3 = s2;
31 cout << s3 ;
32 return 0;
33}
34#endif
35
36#include <iostream>
37#include <cstring>
38#include "MyString.cpp"
39
40using namespace std;
41
42int main1() {
43 // 这里也是一个功能
44 MyString s1(10);
45 cout << "请输入s1" << endl;
46
47 // 重载 >>
48 cin >> s1;
49 cout << s1 << endl;
50
51 return 0;
52}
53
54int main2() {
55 MyString s1;
56 MyString s2("ab");
57
58 MyString s3(s2);
59 s3 = "abcd";
60
61 int flag = (s3 < "bbbb");
62 {
63 if (flag > 0)
64 cout << "s3 > bbbb " << endl;
65
66 else if (flag == 0)
67 cout << "s3 = bbbb " << endl;
68
69 else
70 cout << "s3 < bbbb " << endl;
71 }
72
73 MyString s4 = "abcds";
74 cout << s4 << endl;
75
76 return 0;
77}
78
79int main() {
80 MyString s1;
81 MyString s2("aaa");
82 MyString s3(s1); // MyString s3 = s1;
83 MyString s4("s4444");
84
85
86 // 运算符重载 =
87 // MyString& operator=(MyString & rhs); 函数原型调用s4.operator=(MyString & rhs)
88 s4 = s2;
89
90 // 也是调用运算符重载 MyString& operator=(const char *p);
91 s4 = "2222";
92
93 s4[0]; // 所以说 []重载时 最后是返回一个引用
94 cout << "当右值 s4[0] = " << s4[0] << endl;
95
96 s4[0] = 'a';
97 cout << "当左值 s4[0] = " << s4[0] << endl;
98
99 // s4.operator[](int index);
100 // char& operator[](int index) // 当左值,当右值
101
102
103 // << 重载
104 cout << s4 << endl;
105 // MyString& operator<<(ostream &out, MyString &rhs)
106
107
108 // == 重载
109 if (s2 == "aaa") {
110 cout << "相等" << endl;
111 } else {
112 cout << "不相等" << endl;
113 }
114
115 // if (s2 != "abcd")
116 // s2.operator==(const char *p)
117 // bool operator==(const char *p)
118
119 if (s2 == s4) {
120 cout << "相等" << endl;
121 } else {
122 cout << "不相等" << endl;
123 }
124 // if (s2 != s4)
125
126 // bool operator==(const MyString &rhs)
127
128 cout << "Hello world!" << endl;
129 return 0;
130}
131
132
MyString.h
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 1//
2// Created by lk on 18-6-10.
3//
4
5#ifndef CESHI_MYSTRING_H
6#define CESHI_MYSTRING_H
7
8#include <cstring>
9#include <iostream>
10
11using namespace std;
12
13class MyString {
14 friend ostream &operator<<(ostream &out, const MyString &obj);
15
16 friend istream &operator>>(istream &in, MyString &obj);
17
18public:
19 // 构造
20 MyString();
21
22 MyString(const char *data);
23
24 MyString(const int leng);
25
26 // 拷贝构造
27 MyString(const MyString &obj);
28
29 ~MyString();
30
31public:
32 MyString &operator=(const MyString &obj);
33
34 MyString &operator=(const char *data);
35
36 bool operator==(const MyString &obj) const; // const表示this->m_data不能修改
37 bool operator!=(const MyString &obj) const;
38
39 bool operator==(const char *data) const;
40
41 bool operator!=(const char *data) const;
42
43public:
44 int operator>(const MyString &obj) const;
45
46 int operator<(const MyString &obj) const;
47
48 int operator>(const char *data) const;
49
50 int operator<(const char *data) const;
51
52public:
53
54 char &operator[](const int index) const;
55
56private:
57 char *m_data;
58 int len;
59};
60
61#endif //CESHI_MYSTRING_H
62
63
MyString.cpp
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 1//
2// Created by lk on 18-6-10.
3//
4#include "MyString.h"
5
6//#include <cstring>
7// 无参构造函数
8inline MyString::MyString() {
9 len = 0;
10 m_data = new char[1];
11 strcpy(m_data, "");
12}
13
14inline MyString::MyString(const char *data) {
15 // 如果有初始值
16 if (data) {
17 len = strlen(data);
18 m_data = new char[len + 1];
19 strcpy(m_data, data);
20 } else {
21 len = 0;
22 m_data = new char[1];
23 strcmp(m_data, "");
24 }
25
26}
27
28inline MyString:: //构造一个空串
29MyString(const int leng) {
30 /*
31 if (len == 0)
32 {
33 m_len = 0;
34 m_p = new char[m_len + 1];
35 strcpy(m_p, "");
36 }
37 else
38 {
39 m_len = len;
40 m_p = new char[m_len + 1];
41 // strcpy(m_p, ""); 哪一个都行
42 memset(m_p, 0, m_len);
43 }
44
45 */
46 len = leng;
47 m_data = new char[len + 1];
48 strcpy(m_data, ""); // 构造空串
49}
50
51
52// MyString s1 = s2; 拷贝构造
53inline MyString::
54MyString(const MyString &obj) {
55 len = strlen(obj.m_data);
56 m_data = new char[len + 1];
57 strcpy(m_data, obj.m_data);
58
59}
60
61// 析构函数
62inline MyString::~MyString() {
63 if (m_data != NULL) {
64 len = 0;
65 delete[]m_data;
66 this->m_data = NULL; // 防止出现野指针
67 }
68}
69
70// s1 = s2 = s3; 拷贝赋值
71inline MyString &MyString::operator=(const MyString &obj) {
72 // 提高水平的判断, 就是如果是自己赋值给自己的话,就要加上这句,必须加
73 // 如果this 等于obj对象的指针, 这里的&是取地址
74 if (this == &obj) {
75 return *this;
76 }
77 // 释放旧内存
78 if (m_data != NULL) {
79 len = 0;
80 delete[]m_data;
81 m_data = NULL;
82 }
83
84 // 分配新内存 并赋值
85 len = strlen(obj.m_data);
86 m_data = new char[len + 1];
87 strcpy(m_data, obj.m_data);
88
89 return *this;
90}
91
92// 拷贝赋值 s1 ="aaa"
93inline MyString &MyString::operator=(const char *data) {
94// if (data != NULL)
95 // 释放旧内存
96 if (m_data == NULL) {
97 delete[]m_data;
98 len = 0;
99 m_data = NULL;
100 }
101 // 分配新内存
102 if (data == NULL) {
103 len = 0;
104 m_data = new char[1];
105 strcpy(m_data, "");
106 } else {
107 len = strlen(data);
108 m_data = new char[len + 1];
109 strcpy(m_data, data);
110 }
111 return *this;
112
113
114}
115
116inline bool
117MyString::operator==(const MyString &obj) const {
118 if (len != obj.len)
119 return false;
120 else {
121 if (!strcmp(m_data, obj.m_data))
122 return true;
123 else
124 return false;
125
126 }
127}
128
129inline bool
130MyString::operator!=(const MyString &obj) const {
131 return !(*this == obj);
132}
133
134inline bool
135MyString::operator==(const char *data) const {
136 if (strlen(data) != len) {
137 return false;
138 } else {
139 if (!strcmp(data, m_data))
140 return true;
141 return false;
142 }
143}
144
145inline bool
146MyString::operator!=(const char *data) const {
147 return !(*this == data);
148}
149
150inline int
151MyString::operator<(const MyString &obj) const {
152 return strcmp(m_data, obj.m_data);
153}
154
155inline int
156MyString::operator>(const MyString &obj) const {
157 return strcmp(obj.m_data, m_data);
158}
159
160inline int
161MyString::operator>(const char *data) const {
162 return strcmp(m_data, data);
163}
164
165inline int
166MyString::operator<(const char *data) const {
167 return strcmp(data, m_data);
168}
169
170// s[2]
171inline char & // 多看
172MyString::operator[](const int index) const {
173 static char sNull = '\0';
174 if (strlen(m_data) > index + 1 && index >= 0)
175 return m_data[index];
176 else {
177 cout << "下标越界" << endl;
178 return sNull;
179 }
180}
181
182
183// << 重载 应该是友元 注意返回值,
184// cout << s4 << endl; 全局的
185// friend ostream& operator<<(ostream &out, MyString &obj);
186inline ostream &operator<<(ostream &out, const MyString &obj) {
187 return out << obj.m_data << endl; // 如果是*obj.m_data则是 第一个元素
188}
189
190inline istream &operator>>(istream &in, MyString &obj) {
191 return in >> obj.m_data;
192}
193
194MyString.cpp
195
196