MyString.h 文件
#ifndef _STRING_H_ #define _STRING_H_ #include <iostream> using namespace std; class MyString { public: /*默认的无参和cons char *参数的构造函数; *如果不想允许MyString str="abc"类型的赋值,可将其声明为explicit */ MyString(const char* str=""); //复制构造函数 MyString(const MyString& other); /*重载赋值操作符, *返回值为自身的引用是为了支持连续赋值,如str1 = str2 =str3; *返回值为const是为了禁止(str1=str2)=str3这样的等式 */ const MyString& operator=(const MyString& other); const MyString& operator=(const char* str); bool operator!() const; //重载!操作符, const函数内不会改变类的数据成员 /* 重载[]操作符 *重载此操作符后可以使用下标访问对象元素,拥有和字符串数组相同的功能 *传入的值必须是无符号整数,返回一个char 引用是为了允许MyString str("abc"); str[0]='c';这样的赋值操作 */ char& operator[](unsigned int index); /* *如果不想允许上面的赋值,可以返回const型,这样就只能读取了; 此外函数定义为const含有一个好处:可以被const对象访问; *char ch =str[0];// 合法 *str[0]=ch; //非法 */ const char& operator[](unsigned int index) const; /*重载+操作符,连接两个字符串 *为什么不把该重载函数设为类成员函数? 如果将+重载为成员函数,则左操作数必须为MyString类型 *同时,由于MyString有隐式类型转换构造函数,这里的两个参数可以使MyString类型的也可以是const char * 或者char * *由语义可知,返回值不应为引用; * 定义为友元是因为该函数需要访问类的私有成员,且该函数职位该类使用 */ friend MyString operator+(const MyString& s1, const MyString& s2); /*重载+=操作符 * 这里可以声明为类成员函数,因为左操作数肯定是MyString类型; */ MyString& operator+=(const MyString& other); //声明为友元函数是因为,不能再ostream内重载<< >> 操作符,返回引用是为了支持连续输出或输入 friend ostream& operator<<(ostream& os, const MyString& str); friend istream& operator>>(istream& is, MyString& str); ~MyString(void); void Display() const; unsigned int length(){ return strlen(str_); } private: MyString& Assign(const char* str); char* AllocAndCpy(const char* str); char* str_; }; #endif // _STRING_H_
MyString.cpp 文件
#pragma warning(disable:4996) #include "MyString.h" #include <string.h> //#include <iostream> //using namespace std; MyString::MyString(const char* str) { str_ = AllocAndCpy(str); } MyString::MyString(const MyString& other) { str_ = AllocAndCpy(other.str_); } const MyString& MyString::operator=(const MyString& other) { if (this == &other) // 防止自我赋值 return *this; return Assign(other.str_); } const MyString& MyString::operator=(const char* str) { return Assign(str); } MyString& MyString::Assign(const char* str) { char * newStr = AllocAndCpy(str); if(newStr != NULL){ delete[] str_; // 预防在分配内存是出错,在这里分配成功后再delete str_ = newStr; } return *this; } bool MyString::operator!() const { return strlen(str_) != 0; } char& MyString::operator[](unsigned int index) { //return str_[index]; //non const 版本调用 const版本 return const_cast<char&>(static_cast<const MyString&>(*this)[index]); } const char& MyString::operator[](unsigned int index) const { return str_[index]; } MyString::~MyString() { delete[] str_; } char* MyString::AllocAndCpy(const char* str) { int len = strlen(str) + 1; char* newstr = new char[len]; memset(newstr, 0, len); strcpy(newstr, str); return newstr; } void MyString::Display() const { cout<<str_<<endl; } MyString operator+(const MyString& s1, const MyString& s2) { MyString str = s1; str += s2; return str; } MyString& MyString::operator+=(const MyString& other) { int len = strlen(str_) + strlen(other.str_) + 1; char* newstr = new char[len]; memset(newstr, 0, len); strcpy(newstr, str_); strcat(newstr, other.str_); delete[] str_; str_ = newstr; return *this; } ostream& operator<<(ostream& os, const MyString& str) { os<<str.str_; return os; } istream& operator>>(istream& is, MyString& str) { char tmp[1024]; cin>>tmp; str = tmp; return is; }
main.cpp
#include "MyString.h" #include <iostream> using namespace std; int main(void) { //构造函数测试 { MyString str; MyString str1="nihao"; MyString str2("hello"); MyString str3=str2; cout << "str: length:"<<str.length()<<" :"<<str<<endl; cout << "str1: length:"<<str1.length()<<" :"<<str1<<endl; cout << "str2: length:"<<str2.length()<<" :"<<str2<<endl; cout << "str3: length:"<<str3.length()<<" :"<<str3<<endl; /*输出 str: length:0 : str1: length:5 :nihao str2: length:5 :hello str3: length:5 :hello */ } // 操作符重载测试 { MyString str1,str2,str3; str3 =str2 = str1 = "hello"; cout << str1 << " "<<str2<<" "<<str3<<endl; str1=""; cout << !str1 << " : "<<!str2<<endl; str2[0] = 'H'; str2 += "world"; str3 = str2 + "!"; cout << "str1: length:"<<str1.length()<<" :"<<str1<<endl; cout << "str2: length:"<<str2.length()<<" :"<<str2<<endl; cout << "str3: length:"<<str3.length()<<" :"<<str3<<endl; /* hello hello hello 0 : 1 str1: length:0 : str2: length:10 :Helloworld str3: length:11 :Helloworld! */ } //内存泄露测试 { while(true){ MyString str; MyString str1="nihao"; MyString str2("hello"); MyString str3=str2+str1; str1="hello world"; str1.Display(); str2 += str3; } } return 0; }