C++反复遗忘--自定义String类

  1. 在学习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关键字组织此类隐式转换。

最后,你的每一句留言都让博主欣喜若狂。

原文地址:https://www.cnblogs.com/PPWEI/p/13686169.html