转自天之痕博客
C++继承了C语言中以空字符结尾的C风格字符串以及包括strcpy()函数的函数库,但这些函数没有集成到面向对象的框架中,标准库中包含一个String类,它提供了一套封装好的数据以及处理这些数据的函数,使用这个类前可以先实现一下自定义的String类,以便熟悉这个框架。
代码清单:
- #include <iostream>
- #include <string.h>
- using namespace std;
- class String
- {
- public:
- //constructors
- String();
- String(const char *const);
- String(const String &);
- //destructors
- ~String();
- //操作符重载
- char & operator[] (unsigned short offset); //[]重载非常量版本
- char operator[] (unsigned short offset) const; //[]重载常量版本
- String operator+ (const String &);
- void operator+= (const String &);
- String & operator= (const String &);
- //常规存取器方法
- unsigned short GetLen()const { return itsLen; }
- const char* GetString() const { return itsString; }
- private:
- String(unsigned short); //私有构造函数
- char* itsString;
- unsigned short itsLen;
- };
- String::String()
- {
- itsString=new char[1];
- itsString[0]='/0';
- itsLen=0;
- }
- String::String(unsigned short len)
- {//传入长度,创建一个String对象
- itsString=new char[len+1];
- for (unsigned short i=0;i<=len;i++)
- {
- itsString[i]='/0';
- }
- itsLen=len;
- }
- String::String(const char* const cString)
- {//传入字符串地址,创建一个String对象
- itsLen=strlen(cString);
- itsString=new char[itsLen+1];
- for (unsigned short i=0;i<itsLen;i++)
- itsString[i]=cString[i];
- itsString[itsLen]='/0';
- }
- String::String(const String & rhs)
- {//copy constructors
- itsLen=rhs.GetLen();
- itsString=new char[itsLen+1];
- for(unsigned short i=0;i<itsLen;i++)
- itsString[i]=rhs[i];
- itsString[itsLen]='/0';
- }
- String::~String()
- {
- delete [] itsString;
- itsLen=0;
- }
- String& String::operator=(const String & rhs)
- {
- if(this== &rhs)
- return *this;
- delete [] itsString;
- itsLen=rhs.GetLen();
- itsString=new char[itsLen+1];
- for(unsigned short i=0;i<itsLen;i++)
- itsString[i]=rhs[i];
- itsString[itsLen]='/0';
- return *this;
- }
- char & String::operator [](unsigned short offset)
- {//若偏移大于字符串长度,返回最后一个元素,否则返回字符串偏移处的字符
- if(offset>itsLen)
- return itsString[itsLen-1];
- else
- return itsString[offset];
- }
- char String::operator [](unsigned short offset) const
- {
- if(offset>itsLen)
- return itsString[itsLen-1];
- else
- return itsString[offset];
- }
- String String::operator+ (const String& rhs)
- {
- unsigned short totalLen=itsLen+rhs.GetLen();
- String temp(totalLen);
- unsigned short i,j;
- for(i=0;i<itsLen;i++)
- temp[i]=itsString[i];
- for(j=0;j<rhs.GetLen();j++,i++)
- temp[i]=rhs[j];
- temp[totalLen]='/0';
- return temp;
- }
- void String::operator+= (const String& rhs)
- {
- unsigned short rhsLen=rhs.GetLen();
- unsigned short totalLen=itsLen+rhsLen;
- String temp(totalLen);
- unsigned short i,j;
- for(i=0;i<itsLen;i++)
- temp[i]=itsString[i];
- for(j=0;j<rhsLen;j++,i++)
- temp[i]=rhs[j];
- temp[totalLen]='/0';
- *this=temp;
- }
- int main()
- {
- String s1("initial test");
- cout << "S1:/t"<<s1.GetString()<<endl;
- char* temp="Hello World";
- s1=temp;
- cout << "S1:/t"<<s1.GetString()<<endl;
- char tempTwo[20];
- strcpy(tempTwo,"; nice to be here!");
- s1+=tempTwo;
- cout << "tempTwo:/t" << tempTwo <<endl;
- cout << "S1:/t"<<s1.GetString()<<endl;
- cout << "S1[4]:/t" <<s1[4] <<endl;
- s1[4]='x';
- cout << "S1[4]:/t" <<s1[4] <<endl;
- cout <<"S1[999]:/t" <<s1[999] <<endl;
- String s2(" Another string");
- String s3;
- s3=s1+s2;
- cout << "S3:/t"<<s3.GetString()<<endl;
- String s4;
- s4="Why does this work?";
- cout << "S4:/t"<<s4.GetString()<<endl;
- return 0;
- }
- //S1: initial test
- //S1: Hello World
- //tempTwo: ; nice to be here!
- //S1: Hello World; nice to be here!
- //S1[4]: o
- //S1[4]: x
- //S1[999]: !
- //S3: Hellx World; nice to be here! Another string
- //S4: Why does this work?
- //Press any key to continue
需要注意的几点是:
1.重载'='运算符的函数中,其实返回值是没有作用的,你可以任意返回void或int,凭你喜好。
2.重载[ ]运算符的函数有2个,const类型和非const类型,在142行中,调用的是非const类型,其余对于const类型的对象或对象引用,非const类型函数访问时非法的。
3.第137行中 s1+=tempTwo 这里tempTwo字符数组怎么能和对象进行'+'运算呢? 原来第10行声明了一个可根据字符数组创建String的构造函数,因此编译器根据提供的字符数组创建一个临时String,并将其传递给赋值运算符。这被称为隐式强制转换或升格。如果没有声明并实现接受字符数组作为参数的构造函数,这种赋值将导致错误。