實現一個自定義的String類
阿新 • • 發佈:2019-01-31
C++繼承了C語言中以空字元結尾的C風格字串以及包括strcpy()函式的函式庫,但這些函式沒有整合到面向物件的框架中,標準庫中包含一個String類,它提供了一套封裝好的資料以及處理這些資料的函式,使用這個類前可以先實現一下自定義的String類,以便熟悉這個框架。
程式碼清單:
- #include <iostream>
- #include <string.h>
- usingnamespace std;
- class String
- {
- public:
- //constructors
- String();
- String(constchar *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; }
- constchar* GetString() const { return itsString; }
- private:
- String(unsigned short); //私有建構函式
- char* itsString;
- unsigned short itsLen;
- };
- String::String()
- {
- itsString=newchar[1];
- itsString[0]='/0';
- itsLen=0;
- }
- String::String(unsigned short len)
- {//傳入長度,建立一個String物件
- itsString=newchar[len+1];
- for (unsigned short i=0;i<=len;i++)
- {
- itsString[i]='/0';
- }
- itsLen=len;
- }
- String::String(constchar* const cString)
- {//傳入字串地址,建立一個String物件
- itsLen=strlen(cString);
- itsString=newchar[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=newchar[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=newchar[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,並將其傳遞給賦值運算子。這被稱為隱式強制轉換或升格。如果沒有宣告並實現接受字元陣列作為引數的建構函式,這種賦值將導致錯誤。