- 在学习C++诡异的语法的时候,由于没有正式的使用C++作为工作使用的语言,所以经常遗忘,这就需要反复的学习。而C++的友元函数和运算符重载如果不经常使用,真的很容易忘记。
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 class String 7 { 8 public: 9 ~String(); 10 String(); //无参 11 String(const char *s); //有参 12 String(const String &obj); //拷贝 13 14 String &operator=(const String &obj); 15 String &operator=(const char *s); 16 17 friend String operator+(const String &obj1, const String &obj2); // str1 + str2 全局函数实现(友元函数实现),也可以使用成员函数实现 18 19 friend ostream &operator<<(ostream &out, const String &obj); 20 friend istream &operator>>(istream &in, const String &obj); 21 22 String &operator+=(const String &obj); //str1+=str2 23 String &operator+=(const char *s); 24 25 char &operator[](const int idx) const; //返回引用,可以利用下标修改内容 26 27 private: 28 char *_arr; 29 unsigned int _len; 30 }; 31 String::~String() 32 { 33 delete _arr; 34 _arr = NULL; 35 } 36 String::String() 37 { 38 cout << "String()" << endl; 39 _len = 0; 40 _arr = new char[1]; 41 } 42 String::String(const char *s) 43 { 44 cout << "String(const char *s)" << endl; 45 _len = strlen(s); 46 _arr = new char[_len + 1]; 47 strcpy(_arr, s); 48 } 49 String::String(const String &obj) 50 { 51 cout << "String(const String &obj)" << endl; 52 _len = obj._len; 53 _arr = new char[_len + 1]; 54 strcpy(_arr, obj._arr); 55 } 56 String &String::operator=(const String &obj) 57 { 58 cout << "operator=(const String&)" << endl; 59 delete _arr; 60 _len = obj._len; 61 _arr = new char[_len + 1]; 62 strcpy(_arr, obj._arr); 63 return *this; 64 } 65 String &String::operator=(const char *s) 66 { 67 cout << "oeprator=(const char*)" << endl; 68 delete _arr; 69 _len = strlen(s); 70 _arr = new char[_len + 1]; 71 strcpy(_arr, s); 72 return *this; 73 } 74 String operator+(const String &obj1, const String &obj2) 75 { 76 cout << "operator+(const String &, const String&)" << endl; 77 String s; 78 s._len = obj1._len + obj2._len; 79 s._arr = new char[s._len + 1]; 80 strcpy(s._arr, obj1._arr); 81 strcat(s._arr, obj2._arr); 82 return s; 83 } 84 ostream &operator<<(ostream &out, const String &obj) 85 { 86 cout << "operator<<(ostream&, const String &obj)" << endl; 87 out << obj._arr; 88 return out; 89 } 90 istream &operator>>(istream &in, const String &obj) 91 { 92 cout << "operator>>(istream&, const String &obj)" << endl; 93 in >> obj._arr; 94 return in; 95 } 96 String &String::operator+=(const String &obj) 97 { 98 cout << "operator+=(const String &obj)" << endl; 99 char *temp = _arr; 100 _len += obj._len; 101 _arr = new char[_len + 1]; 102 strcpy(_arr, temp); 103 strcat(_arr, obj._arr); 104 delete temp; 105 return *this; 106 } 107 String &String::operator+=(const char *s) 108 { 109 cout << "operator+=(const char *s)" << endl; 110 char *temp = _arr; 111 _len += strlen(s); 112 _arr = new char[_len + 1]; 113 strcpy(_arr, temp); 114 strcat(_arr, s); 115 delete temp; 116 return *this; 117 } 118 char &String::operator[](const int idx) const 119 { 120 cout << "operator[]" << endl; 121 return _arr[idx]; 122 } 123 124 int main() 125 { 126 String s0; 127 String s1("hello"); 128 String s2(s1); 129 String s3 = s2; //执行拷贝构造,类似于 String s2(s1) 130 String s4 = "world"; //执行有参构造,类似于 String s1("hello") 131 132 s0 = s3; //执行operator=(const String &) 133 s0 = "good"; //执行operator=(const char*) 134 135 String s5 = s1 + s4; 136 s5 = s1 + s4; //执行operator+ 、String()、operator= 三个函数 137 cout << s5 << endl; //输出 helloworld 138 s5 += s1; 139 cout << s5 << endl; //输出 helloworldhello 140 s5 += "world"; 141 cout << s5 << endl; //输出 helloworldhelloworld 142 char c0 = s5[0]; 143 cout << c0 << endl; //输出 h 144 s5[0] = 'x'; 145 cout << s5 << endl; //输出 xelloworldhelloworld 146 cin >> s5; //输入 hahaha 147 cout << s5 << endl; //输出 hahaha 148 149 return 0; 150 }
对应以上代码的输出:
1 oop % ./String 2 String() 3 String(const char *s) 4 String(const String &obj) 5 String(const String &obj) 6 String(const char *s) 7 operator=(const String&) 8 oeprator=(const char*) 9 operator+(const String &, const String&) 10 String() 11 operator+(const String &, const String&) 12 String() 13 operator=(const String&) 14 operator<<(ostream&, const String &obj) 15 helloworld 16 operator+=(const String &obj) 17 operator<<(ostream&, const String &obj) 18 helloworldhello 19 operator+=(const char *s) 20 operator<<(ostream&, const String &obj) 21 helloworldhelloworld 22 operator[] 23 h 24 operator[] 25 operator<<(ostream&, const String &obj) 26 xelloworldhelloworld 27 operator>>(istream&, const String &obj) 28 hahaha #此行为输入 29 operator<<(ostream&, const String &obj) 30 hahaha 31 oop %
需要强调的是,运算符重载中有一个非常特殊的存在,那就是‘=’,它和拷贝构造函数有一定的功能重叠。当仅定义其中一个时(比如,只定义拷贝构造),使用‘=’运算符时同样不会报错,这是因为编译器对函数调用做了隐式转换。我的理解是,在不能完全肯定不会出错的情况下,要么就把各种情况下的函数都定义一遍,尽量不让编译器做出隐式转换,或者使用explicit关键字组织此类隐式转换。
最后,你的每一句留言都让博主欣喜若狂。