欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解C++中實(shí)現(xiàn)繼承string類的MyString類的步驟

 更新時間:2016年04月21日 16:53:43   作者:mifan88  
這篇文章主要介紹了C++中實(shí)現(xiàn)繼承string類的MyString類的步驟,其中的要點(diǎn)是要實(shí)現(xiàn)運(yùn)算符的重載,需要的朋友可以參考下

昨天師兄又出了道測試題,讓我們實(shí)現(xiàn)類似于string類的沒有MyString類,剛開始很頭疼,可是真正在自己寫代碼的時候又很興奮的發(fā)現(xiàn),這個過程真的是個很寶貴的機(jī)會,讓我又有機(jī)會可以很好的熟悉回顧C(jī)++的很多知識—類設(shè)計(jì),構(gòu)造析構(gòu)函數(shù),成員函數(shù),友元函數(shù),引用,重載,字符串操作,動態(tài)內(nèi)存分布。。。。。于是昨天花了半天時間寫了300多行代碼,并認(rèn)真的進(jìn)行了相關(guān)測試、修改和總結(jié)。因?yàn)閮?nèi)容有點(diǎn)豐富,所以想分幾次寫出來,條理也清楚些。

類的空間分配:類給它的每個對象都分配了獨(dú)立的空間去存儲它的數(shù)據(jù)成員,所有的對象公共的訪問類方法進(jìn)行操作。同時在對象的獨(dú)立空間中,不包括數(shù)據(jù)成員動態(tài)分配的空間,對象只是記錄了動態(tài)分配空間的地址(所以在析構(gòu)函數(shù)調(diào)用的時候只是刪除了對像空間,同時需要用new來刪除動態(tài)分配的地址)。

一、類聲明—mystring.h:
1. 構(gòu)造函數(shù):
專門用于構(gòu)建新對象,給成員數(shù)據(jù)分配必要的內(nèi)存空間并將值賦給新對象的成員數(shù)據(jù)。
默認(rèn)構(gòu)造函數(shù):
在未提供顯式初始化值時,被用來創(chuàng)建對象的構(gòu)造函數(shù)(所以它一般沒有參數(shù))

MyString();

復(fù)制構(gòu)造函數(shù):
用于將一個對象復(fù)制到新創(chuàng)建的對象中(當(dāng)然這個被復(fù)制的對象必須已經(jīng)存在)。

MyString(const MyString &str);

給定了一定初始化參數(shù)的構(gòu)造函數(shù):
參數(shù)列表中的值會一次賦給新創(chuàng)建對象的各個成員函數(shù):

MyString(const char*str);

2.析構(gòu)函數(shù):
當(dāng)對象過期時刪除對象所占的內(nèi)存空間,并且當(dāng)對象創(chuàng)建時有用New請求的內(nèi)存空時,在析構(gòu)函數(shù)中同時要調(diào)用delete對原來分配的 內(nèi)存空間進(jìn)行釋放,以防止內(nèi)存泄露。
~MyString();

3.成員函數(shù):
重載賦值成員函數(shù):

MyString &operator=(const MyString &str);    //利用已有的string對象通過=給一個對象進(jìn)行賦值
MyString &operator=(const char*str);       //直接用常量字符串進(jìn)行賦值

一般賦值函數(shù):

MyString &assign(const MyString&str);
MyString &assign(const char*sstr);

幾個處理字符串的成員函數(shù):

size_t getsize()const;                  //返回字符串大小
void clear();                      //把字符串清空
bool empty();                       //判斷字符串是否為空
void swap(MyString &str);              //交換兩個字符串
int compare(const MyString &str)const;      //比較2個字符串的大小
//第一個const說明顯式調(diào)用的字符串不可更改,括號外面的const說明隱式調(diào)用的字符串不可更改,只讀數(shù)據(jù)    
int compare(const char*str);           

追加函數(shù):

MyString &operator+=(const MyString&str);
MyString &operator+=(const char*str);
MyString &append(const MyString&str);
MyString &append(const char *str);

生成字串:

MyString substr(size_t pos = 0,n=npos) const; 
生成字串,從第0個位置開始長度為n,若N超過長度,則為輸出整個字符串的長度

4.友元函數(shù)(運(yùn)算符重載):
友元函數(shù)一般都是在類得聲明中進(jìn)行定義,它不屬于類得成員函數(shù),但是它和類得成員函數(shù)一樣同樣的可以對類得所有數(shù)據(jù)成員進(jìn)行訪問。

friend bool operator==(const MyString &str1,const MyString &str2);
friend bool operator==(const char *str,const MyString &str2);
friend bool operator==(const MyString &str1,const MyString *str2);
friend bool operator>(const MyString &str1,const MyString &str2);
friend bool operator>(const char*str1,const MyString &str2);
friend bool operator>(const MyString &str1,const char*str2);

同樣還有<等各種比較。

friend MyString operator+(const MyString &str1,const MyString &str2);
friend MyString operator+(const char*str1,const MyString &str2);      //兩個字符串進(jìn)行相加
friend MyString operator+(const MyString &str1,const char*str2);

friend ostream & operator<<(ostream &os,const MyString &str);       //輸出命令符的重載

5.成員數(shù)據(jù)變量:

char *string;                     //指向字符串的指針
int length;                       //字符串的長度
static const int string_number = 0;      //計(jì)數(shù)創(chuàng)建的字符串的數(shù)目

二、實(shí)現(xiàn).cpp文件:
1.構(gòu)造函數(shù)和析構(gòu)函數(shù):

MyString::MyString() 
{ 
  length = 0; 
  string = new char; 
  char *s = "/0"; 
  memcpy(string,s,1); 
  ++string_number; 
} 
 
MyString::MyString(const char*str) 
{ 
  length = strlen(str); 
  string = new char(length+1); 
  memcpy(string,s,length); 
  ++string_number; 
} 
MyString::MyString(MyString &str) 
{ 
  length = str.length; 
  string = str.string; 
  ++string_number; 
} 
 
MyString::~MyString() 
{   
  delete[]string; 
  --string_number; 
} 

幾個注意的問題:
1)構(gòu)造函數(shù)中必須給所有的數(shù)據(jù)成員進(jìn)行初始化。
2)注意在給指向字符串的指針賦值時,左右類型的對應(yīng)。
char *s代表一個指向字符串的指針,所有右邊必須是一個字符串常量“/0”,而不能是‘/0'.
3)一個指針只能指向一個地址,不能同時指向兩個。
在給string分配了地址之后,下一步我們肯定是確定分配的地址中存放的具體內(nèi)容,那么這個時候我們都是使用strcpy()或者是
memcpy()把對應(yīng)的字符串存入地址中。
如果原來我們成這樣實(shí)現(xiàn):

   MyString::MyString()
  {
    length = 0;
    string = new char;
    string = "/0";
    ++string_number;
  }

那么我們在編譯和實(shí)現(xiàn)的時候都不會發(fā)現(xiàn)有什么錯,但是析構(gòu)函數(shù)使用delete【】釋放內(nèi)存使執(zhí)行結(jié)果會出現(xiàn)亂碼,因?yàn)閟tring=“/0”
讓它指向了一個字符串,并沒有分配內(nèi)存空間,所以在釋放的時候就會出現(xiàn)錯誤。
4)析構(gòu)函數(shù)中的重要語句 delete【】不要忘
析構(gòu)函數(shù)在使用的時候只會釋放為對象分配的空間,但是對象的空間中只是存儲了數(shù)據(jù)成員分配內(nèi)存的地址,所以并沒有釋放數(shù)據(jù)成員
的內(nèi)存空間,必須使用delete[]來進(jìn)行釋放,防止內(nèi)存泄露 
2.重載運(yùn)算符的成員函數(shù):

MyString &MyString::operator+=(const MyString&str) 
{ 
   char *dest; 
   dest = new char[str.length+length+1]; 
   memcpy(dest,string,length); 
   memcpy(dest+length,str.string,str.length+1); 
   delete[]string; 
   length = length+str.length; 
   string = dest; 
   return*this; 
} 
MyString &MyString::operator+=(const char*str) 
{ 
   char *dest; 
   dest = new char[strlen(str)+length+1]; 
   memcpy(dest,string,length); 
   memcpy(dest+length,str,strlen(str)+1); 
   delete[]string; 
   string = dest; 
   return *this; 
} 
 
 //字符串賦值 
MyString &MyString::operator=(const MyString&str) 
{ 
  if(&str == this) 
    return *this; 
  delete[]string; 
  string = new char[str.length]; 
  memcpy(string,str.string,str.length); 
  length = str.length; 
  return *this; 
} 

 
注意的幾個問題:
1)+=運(yùn)算中,調(diào)用函數(shù)的對象最終字符串長度肯定大于其原來的長度,所以在這個函數(shù)調(diào)用過程中,我們必須給字符串重新分配一塊
兩個字符串長度和大小的內(nèi)存區(qū)域。但是因?yàn)楹瘮?shù)返回值又必須是原調(diào)用對象的引用,所以我們要定義一個中間變量指針來存儲2個
字符串合并結(jié)果,最后釋放string指針原來的內(nèi)存區(qū)域后,再讓它指向合并字符串。
2)“=”賦值運(yùn)算肯定和構(gòu)造函數(shù)的初始化不一樣。
在使用這個方法以前,那么對象肯定至少已經(jīng)通過調(diào)用構(gòu)造函數(shù)數(shù)據(jù)成員有了一定的值。所以這個時候我們首先判斷兩個對象是否
相等。相等的話返回原對象,如果不等:
那么兩個對象的字符串長度肯定不同。所以我們先釋放原字符串內(nèi)存空間,然后根據(jù)賦值對象的字符串長度分配內(nèi)存空間并把字符
串內(nèi)存拷貝過去。
3.字符串處理的幾個函數(shù):

size_t MyString::getsize(MyString &str) 
{ 
 return strlen(str.string); 
} 
void MyString::clear() 
{ 
 length = 0; 
 while(string!='/0') 
 *string ='/0'; 
} 
bool MyString::empty() 
{ 
 return strlen(string)==0; 
} 
int MyString ::compare(const MyString &str) 
{ 
  return compare(string,str.string); 
} 
void MyString::swap(MyString &str) 
{ 
  char *temp; 
  temp = string; 
  string = str.string; 
  str = temp; 
} 
Mystring MyString::substr(sizez_t pos=0,size_t n )const 
{ 
  MyString string; 
  delete[]string.string; 
  if(n>length) 
  { 
   string.length = length; 
   string.string = new char[length+1]; 
   memcpy(string.string,string,length+1); 
    return string; 
  } 
  length = n; 
  string.string = new char[length+1]; 
  memcpy(string.string,string,length+1); 
  return string; 
} 

注意的幾個問題:
1)在這幾個函數(shù)的實(shí)現(xiàn)中,我們可以直接調(diào)用c語言中幾個對字符串處理的<string.h>函數(shù)進(jìn)行實(shí)現(xiàn)
2)clear()函數(shù)中注意,只是把每個內(nèi)存區(qū)域的字符置為0,并不能通過delete[]來釋放內(nèi)存空間,這樣很容易和析構(gòu)函數(shù)一起造成
兩次釋放內(nèi)存空間引起錯誤。
3)swap()實(shí)現(xiàn)交換的這個函數(shù)中,我們可以直接定義中間變量指針實(shí)現(xiàn),不用重新分配內(nèi)存空間全部進(jìn)行轉(zhuǎn)存,這個對于析構(gòu)函數(shù)
的析構(gòu)沒有影響。
4.友元函數(shù):

friend bool operator==(const MyString &str1,const MyString &str2) 
 
  return strcmp(str1.string,str2.string)==0; 
 
friend MyString operator+(const MyString &str1,const MyString &str2) 
{ 
  MyString mystring; 
  char *dest; 
  dest = new char[str1.length+str2.length+1]; 
  memcpy(dest,str1.string,str1.length); 
  memcpy(dest+str1.length,str2.string,str2.length+1); 
  delete[]mystring.string; 
  mystring.string = dest; 
  mystring.length = str1.length+str2.length; 
  return mystring; 
} 
friend ostream &operator<<(ostream &os,const MyString &str) 
{ 
  os<<str.string; 
  return os; 
} 

注意的問題和上面差不多,這里就不重復(fù)了~~~
其他幾個函數(shù)實(shí)現(xiàn)都基本雷同~

相關(guān)文章

最新評論