本文仅实现string类中几种重要、常用的功能,旨在掌握C++类设计的关键知识点。
为使代码简洁,本文采取分文件编写模式,类的声明包含在头文件"mystring.h"中,成员的实现包含在源文件"mystring.h"中,"main.cpp"文件是若干测试。
类比C++中原有的string类,我们可以定义一个string对象(不指定初始值),可以用一个已存在的string对象初始化一个新定义的对象,也可以用一个C风格字符串给一个string对象赋值。为了实现同样的功能,自定义的String类需要如下几种构造函数:
由于String类是我们自定义的,所以有必要重载若干常用运算符以丰富String类所支持的功能。具体地,本文将重载一下运算符:
只设计一个length()函数用于获取字符串的长度。
析构函数无法重载较为简单,一个类中只能有一个析构函数,后续介绍析构函数的内部实现,这里不做过多阐述。
只设计一个变量len用于记录字符串的长度。
类的设计部分代码如下:
1 #ifndef MYSTRING_H_INCLUDED 2 #define MYSTRING_H_INCLUDED 3 4 #include <iostream> 5 6 using namespace std; 7 8 class String { 9 public: 10 // constructor function 11 String(); // default constructor function 12 String(const String& s); // copy constructor function 13 String(const char* s); 14 15 // overload function 16 String& operator=(const String& s); // 17 String& operator=(const char* s); 18 String& operator+=(const String& s); 19 friend int operator==(const String& s1, const String& s2); 20 friend int operator>(const String& s1, const String& s2); 21 friend int operator<(const String& s1, const String& s2); 22 char& operator[](int i); 23 const char& operator[](int i) const; 24 friend ostream& operator<<(ostream& os, String& s); 25 friend istream& operator>>(istream& is, String& s); 26 27 // common function 28 int length() const; 29 30 // 31 ~String(); 32 33 private: 34 char* str; 35 int len; 36 }; 37 38 39 40 #endif // MYSTRING_H_INCLUDED
将默认值设置为空,因此只需申请一个char大小的内存空间用于存放C风格字符串结尾标志 ‘\0’。
1 String::String() { 2 len = 0; 3 str = new char[1]; 4 str[0] = '\0'; 5 }
首先判断s是否为空,然后更新新字符串的长度,接着开辟一段内存空间,最后用strcpy()函数将s.str复制到新的字符串中。
1 String::String(const String& s) { 2 if (s.length() == 0) { 3 String(); 4 } 5 len = s.len; 6 str = new char[len + 1]; 7 strcpy(str, s.str); 8 }
普通有参构造函数:String(const String* s)
与拷贝构造函数类似。
1 String::String(const char* s) { 2 if (s == nullptr) { 3 String(); 4 } 5 len = strlen(s); 6 str = new char[len + 1]; 7 strcpy(str, s); 8
先判断等号两侧对象是否相同。释放原对象内存是关键。
1 String& String::operator=(const String& s) { 2 if (this == &s) { 3 return *this; 4 } 5 6 delete []str; 7 int len = s.length(); 8 str = new char[len + 1]; 9 strcpy(str, s.str); 10 11 return *this; 12 }
1 String& String::operator=(const char* s) { 2 delete []str; 3 len = strlen(s); 4 str = new char[len + 1]; 5 strcpy(str, s); 6 7 return *this; 8 }
采用成员函数的方式重载,只需传递一个参数。将运算符左侧对象复制一份到新对象c中,然后删除运算符左侧对象原有的的内存空间,再扩容、字符拷贝、释放临时对象c。
1 String& String::operator+=(const String& s) { 2 String c(*this); 3 delete []this->str; 4 this->str = new char[this->length() + s.length()]; 5 stpcpy(this->str, c.str); 6 stpcpy(this->str, s.str); 7 this->len += s.length(); 8 delete []c.str; 9 10 return *this; 11 }
1 int operator==(const String& s1, const String& s2) { 2 return (strcmp(s1.str, s2.str) == 0); 3 } 4 5 int operator>(const String& s1, const String& s2) { 6 return (strcmp(s1.str, s2.str) > 0); 7 } 8 9 int operator<(const String& s1, const String& s2) { 10 return (strcmp(s1.str, s2.str) < 0); 11 }
1 char& String::operator[](int i) { 2 return str[i]; 3 } 4 const char& String::operator[](int i) const { 5 return str[i]; 6 }
1 ostream & operator<<(ostream& os, String& s) { 2 os << s.str; 3 return os; 4 } 5 6 istream& operator>>(istream& is, String& s){ 7 char temp[80]; 8 cin.getline(temp, 80); 9 //is >> temp; 10 s = temp; 11 12 return is; 13 }
1 int String::length() { 2 return len; 3 }
1 String::~String() { 2 delete []str; 3 }
1 int main() 2 { 3 String str1("abc"); 4 String str2(str1); 5 String str3; 6 str3 = str2; 7 cout << "str1的长度: " << str1.length() << endl; 8 cout << "str1[0] = " << str1[0] << endl; 9 cout << "str1 = " << str1 << endl; 10 cout << "str3 = " << str3 << endl; 11 cin >> str3; 12 cout << "str3 = " << str3 << endl; 13 cout << "str3的长度: " << str3.length() << endl; 14 return 0; 15 }