国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

詳解C++中實現繼承string類的MyString類的步驟

2020-05-23 14:05:18
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了C++中實現繼承string類的MyString類的步驟,其中的要點是要實現運算符的重載,需要的朋友可以參考下
 

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

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

一、類聲明—mystring.h:
1. 構造函數:

專門用于構建新對象,給成員數據分配必要的內存空間并將值賦給新對象的成員數據。
默認構造函數:
在未提供顯式初始化值時,被用來創建對象的構造函數(所以它一般沒有參數)

MyString();

復制構造函數:
用于將一個對象復制到新創建的對象中(當然這個被復制的對象必須已經存在)。

MyString(const MyString &str);

給定了一定初始化參數的構造函數:
參數列表中的值會一次賦給新創建對象的各個成員函數:

MyString(const char*str);

2.析構函數:
當對象過期時刪除對象所占的內存空間,并且當對象創建時有用New請求的內存空時,在析構函數中同時要調用delete對原來分配的 內存空間進行釋放,以防止內存泄露。
~MyString();

3.成員函數:
重載賦值成員函數:

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

一般賦值函數:

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

幾個處理字符串的成員函數:

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

追加函數:

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.友元函數(運算符重載):
友元函數一般都是在類得聲明中進行定義,它不屬于類得成員函數,但是它和類得成員函數一樣同樣的可以對類得所有數據成員進行訪問。

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);      //兩個字符串進行相加friend MyString operator+(const MyString &str1,const char*str2);friend ostream & operator<<(ostream &os,const MyString &str);       //輸出命令符的重載

5.成員數據變量:

char *string;                     //指向字符串的指針int length;                       //字符串的長度static const int string_number = 0;      //計數創建的字符串的數目

二、實現.cpp文件:
1.構造函數和析構函數:

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)構造函數中必須給所有的數據成員進行初始化。
2)注意在給指向字符串的指針賦值時,左右類型的對應。
char *s代表一個指向字符串的指針,所有右邊必須是一個字符串常量“/0”,而不能是‘/0'.
3)一個指針只能指向一個地址,不能同時指向兩個。
在給string分配了地址之后,下一步我們肯定是確定分配的地址中存放的具體內容,那么這個時候我們都是使用strcpy()或者是
memcpy()把對應的字符串存入地址中。
如果原來我們成這樣實現:

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

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

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)+=運算中,調用函數的對象最終字符串長度肯定大于其原來的長度,所以在這個函數調用過程中,我們必須給字符串重新分配一塊
兩個字符串長度和大小的內存區域。但是因為函數返回值又必須是原調用對象的引用,所以我們要定義一個中間變量指針來存儲2個
字符串合并結果,最后釋放string指針原來的內存區域后,再讓它指向合并字符串。
2)“=”賦值運算肯定和構造函數的初始化不一樣。
在使用這個方法以前,那么對象肯定至少已經通過調用構造函數數據成員有了一定的值。所以這個時候我們首先判斷兩個對象是否
相等。相等的話返回原對象,如果不等:
那么兩個對象的字符串長度肯定不同。所以我們先釋放原字符串內存空間,然后根據賦值對象的字符串長度分配內存空間并把字符
串內存拷貝過去。
3.字符串處理的幾個函數:

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)在這幾個函數的實現中,我們可以直接調用c語言中幾個對字符串處理的<string.h>函數進行實現
2)clear()函數中注意,只是把每個內存區域的字符置為0,并不能通過delete[]來釋放內存空間,這樣很容易和析構函數一起造成
兩次釋放內存空間引起錯誤。
3)swap()實現交換的這個函數中,我們可以直接定義中間變量指針實現,不用重新分配內存空間全部進行轉存,這個對于析構函數
的析構沒有影響。
4.友元函數:

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; } 

注意的問題和上面差不多,這里就不重復了~~~
其他幾個函數實現都基本雷同~



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 巴林左旗| 闽清县| 屏东县| 北碚区| 兴文县| 杭州市| 台南县| 建宁县| 清涧县| 左云县| 五莲县| 宜黄县| 嘉祥县| 阳山县| 靖西县| 青冈县| 澳门| 龙川县| 邢台县| 巫溪县| 东乡县| 章丘市| 噶尔县| 胶南市| 汽车| 谷城县| 徐州市| 大理市| 炎陵县| 卓尼县| 肇庆市| 叙永县| 法库县| 西华县| 清原| 安化县| 德州市| 淳化县| 韶山市| 韶山市| 温宿县|