1. 程式人生 > >實現一個自定義的String類

實現一個自定義的String類

C++繼承了C語言中以空字元結尾的C風格字串以及包括strcpy()函式的函式庫,但這些函式沒有整合到面向物件的框架中,標準庫中包含一個String類,它提供了一套封裝好的資料以及處理這些資料的函式,使用這個類前可以先實現一下自定義的String類,以便熟悉這個框架。

程式碼清單:

  1. #include <iostream>
  2. #include <string.h>
  3. usingnamespace std;
  4. class String
  5. {
  6. public:
  7. //constructors
  8.   String();
  9.   String(constchar *const);
  10.   String(
    const String &);
  11. //destructors
  12.   ~String();
  13. //操作符過載
  14. char & operator[] (unsigned short offset);  //[]過載非常量版本
  15. char operator[] (unsigned short offset) const;  //[]過載常量版本
  16.   String operator+ (const String &);
  17. void operator+= (const String &);
  18.   String & operator= (const String &);
  19. //常規存取器方法
  20.   unsigned short GetLen()const { return itsLen; }
  21. constchar* GetString() const { return itsString; }
  22. private:
  23.   String(unsigned short); //私有建構函式
  24. char* itsString;
  25.   unsigned short itsLen;
  26. };
  27. String::String()
  28. {
  29.   itsString=newchar[1];
  30.   itsString[0]='/0';
  31.   itsLen=0;
  32. }
  33. String::String(unsigned short len)
  34. {//傳入長度,建立一個String物件
  35.   itsString=newchar[len+1];
  36. for (unsigned short i=0;i<=len;i++)
  37.   {
  38.     itsString[i]='/0';
  39.   }
  40.   itsLen=len;
  41. }
  42. String::String(constcharconst cString)
  43. {//傳入字串地址,建立一個String物件
  44.   itsLen=strlen(cString);
  45.   itsString=newchar[itsLen+1];
  46. for (unsigned short i=0;i<itsLen;i++)
  47.     itsString[i]=cString[i];
  48.   itsString[itsLen]='/0';
  49. }
  50. String::String(const String & rhs)
  51. {//copy constructors
  52.   itsLen=rhs.GetLen();
  53.   itsString=newchar[itsLen+1];
  54. for(unsigned short i=0;i<itsLen;i++)
  55.     itsString[i]=rhs[i];
  56.   itsString[itsLen]='/0';
  57. }
  58. String::~String()
  59. {
  60. delete [] itsString;
  61.   itsLen=0;
  62. }
  63. String& String::operator=(const String & rhs)
  64. {
  65. if(this== &rhs)
  66. return *this;
  67. delete [] itsString;
  68.   itsLen=rhs.GetLen();
  69.   itsString=newchar[itsLen+1];
  70. for(unsigned short i=0;i<itsLen;i++)
  71.     itsString[i]=rhs[i];
  72.   itsString[itsLen]='/0';
  73. return *this;
  74. }
  75. char & String::operator [](unsigned short offset)
  76. {//若偏移大於字串長度,返回最後一個元素,否則返回字串偏移處的字元
  77. if(offset>itsLen)
  78. return itsString[itsLen-1];
  79. else
  80. return itsString[offset];
  81. }
  82. char String::operator [](unsigned short offset) const
  83. {
  84. if(offset>itsLen)
  85. return itsString[itsLen-1];
  86. else
  87. return itsString[offset];  
  88. }
  89. String String::operator+ (const String& rhs)
  90. {
  91.   unsigned short totalLen=itsLen+rhs.GetLen();
  92.   String temp(totalLen);
  93.   unsigned short i,j;
  94. for(i=0;i<itsLen;i++)
  95.     temp[i]=itsString[i];
  96. for(j=0;j<rhs.GetLen();j++,i++)
  97.     temp[i]=rhs[j];
  98.   temp[totalLen]='/0';
  99. return temp;
  100. }
  101. void String::operator+= (const String& rhs)
  102. {
  103.   unsigned short rhsLen=rhs.GetLen();
  104.   unsigned short totalLen=itsLen+rhsLen;
  105.   String temp(totalLen);
  106.   unsigned short i,j;
  107. for(i=0;i<itsLen;i++)
  108.     temp[i]=itsString[i];
  109. for(j=0;j<rhsLen;j++,i++)
  110.     temp[i]=rhs[j];
  111.   temp[totalLen]='/0';
  112.   *this=temp;
  113. }
  114. int main()
  115. {
  116.   String s1("initial test");
  117.   cout << "S1:/t"<<s1.GetString()<<endl;
  118. char* temp="Hello World";
  119.   s1=temp;
  120.   cout << "S1:/t"<<s1.GetString()<<endl;
  121. char tempTwo[20];
  122.   strcpy(tempTwo,"; nice to be here!");
  123.   s1+=tempTwo;
  124.   cout << "tempTwo:/t" << tempTwo <<endl;
  125.   cout << "S1:/t"<<s1.GetString()<<endl;
  126.   cout << "S1[4]:/t" <<s1[4] <<endl;
  127.   s1[4]='x';
  128.   cout << "S1[4]:/t" <<s1[4] <<endl;
  129.   cout <<"S1[999]:/t" <<s1[999] <<endl;
  130.   String s2(" Another string");
  131.   String s3;
  132.   s3=s1+s2;
  133.   cout << "S3:/t"<<s3.GetString()<<endl;
  134.   String s4;
  135.   s4="Why does this work?";
  136.   cout << "S4:/t"<<s4.GetString()<<endl;
  137. return 0;
  138. }
  139. //S1:     initial test
  140. //S1:     Hello World
  141. //tempTwo:        ; nice to be here!
  142. //S1:     Hello World; nice to be here!
  143. //S1[4]:  o
  144. //S1[4]:  x
  145. //S1[999]:        !
  146. //S3:     Hellx World; nice to be here! Another string
  147. //S4:     Why does this work?
  148. //Press any key to continue

需要注意的幾點是:

1.過載'='運算子的函式中,其實返回值是沒有作用的,你可以任意返回void或int,憑你喜好。

2.過載[ ]運算子的函式有2個,const型別和非const型別,在142行中,呼叫的是非const型別,其餘對於const型別的物件或物件引用,非const型別函式訪問時非法的。

3.第137行中 s1+=tempTwo 這裡tempTwo字元陣列怎麼能和物件進行'+'運算呢? 原來第10行聲明瞭一個可根據字元陣列建立String的建構函式,因此編譯器根據提供的字元陣列建立一個臨時String,並將其傳遞給賦值運算子。這被稱為隱式強制轉換或升格。如果沒有宣告並實現接受字元陣列作為引數的建構函式,這種賦值將導致錯誤。