C++ 實現MyString類【課程設計】
功能實現:
<基本功能>
1> 實現標頭檔案的封裝:MyString.h
2> 預設建構函式對字串的初始化( MyString() )
3> 使用建構函式初始化字串的另外兩種方式 * 2( 動態指標+拷貝建構函式 )
4> 解構函式( 釋放動態申請的字串空間 )
5> 過載輸出運算子( << )
6> 過載賦值運算子 * 2( = )
7> 過載下標運算子( [],索引輸出 )
<拓展功能>
1>
2>
3>
4>
5>
6>
7>
****************************************************************************************************************************************
一: 基本功能 (實現原始碼)
1) MyString.h
#pragma once #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string.h> //會借用strlen與strcpy函式實現相應的功能 using namespace std; class MyString { public: MyString(); MyString(const char *const); MyString(const MyString &); ~MyString(); int length()const; //const函式不能修改其資料成員,僅僅起到輸出資料的作用 int size() const; //和length功能一致 const char * getString() const; //直接呼叫字串首指標返回 friend ostream & operator << (ostream &, const MyString &); //過載輸出運算子 MyString & operator = (const MyString &); MyString & operator = (const char * ); char & operator [] (const int index); private: char * str; //指向陣列首地址(此時為野指標) int len; };
2)MyString.cpp
#include "MyString.h" using namespace std; MyString::MyString() //構造空字串 { str = new char[1]; str[0] = '\0'; len = 0; } MyString::MyString(const char * const P) //按照動態指標來構造相應的字串 { if (P) { len = strlen(P); //取長度 str = new char[len + 1]; //開空間 strcpy(str, P); //複製值 } else { MyString(); //如果傳入的字串為空,直接呼叫預設值建構函式 } } MyString::MyString(const MyString & AnotherMyString) //拷貝建構函式,這裡的形參使用了const,該形參類中的所有函式都要使用const來修飾 { len = AnotherMyString.length(); str = new char[len + 1]; strcpy(str, AnotherMyString.str); } int MyString::length() const //求長度成員函式 { return len; } int MyString::size() const { return len; } const char * MyString::getString()const { return str; } MyString & MyString::operator=(const MyString &AnotherMyString) { if (&AnotherMyString == this) { return *this; } delete[] str; len = AnotherMyString.length(); str = new char[len + 1]; strcpy(str, AnotherMyString.str); return *this; // TODO: 在此處插入 return 語句 } MyString & MyString::operator=(const char * P) { delete[] str; len = strlen(P); str = new char[len + 1]; strcpy(str, P); return *this; // TODO: 在此處插入 return 語句 } char & MyString::operator[](const int index) { if (index > len) //如果索引越界,輸出最後一個字元 { cout << "Warning!!!" << endl; cout << "Out of boundary! The last char is: "; return str[len - 1]; } else { return str[index-1]; } // TODO: 在此處插入 return 語句 } MyString::~MyString() //釋放陣列空間 { delete[] str; len = 0; } ostream & operator << (ostream & output, const MyString & str) //過載輸出運算子 { output << str.getString(); return output; // TODO: 在此處插入 return 語句 }
*這裡需要提到的一點是解構函式中的delete[] str;
<delete[]與delete的區別>
使用new得來的空間使用delete釋放;使用new[]得來的空間使用delete[]釋放;這是永遠不會錯的。
但是更加深入一點去理解:
使用new[]得到的空間如果 動態申請的資料型別時基本資料型別也可以使用delete直接釋放,但是如果使用new[]申請的資料的型別時自定義型別(例如類名),這就必須使用delete[]來進行釋放,只有這樣才能夠呼叫自定義型別的解構函式進行對自定義型別進行釋放。
*除此之外,再提一點關於delete[]的注意事項:
當使用new[]動態生成記憶體的時候,刪除的時候必須將刪除的指標指向new[]出來的記憶體的首地址:
#include <iostream>
using namespace std;
int main()
{
int *p = new int[3];
*p = 1;
p++;
*p = 2;
delete[]p;
cout << "*" << endl;
return 0;
}
這一段小程式中:
因為p指標不是指向了首地址,所以程式雖然沒報錯,但是無法正常執行!我們可以將申請的首地址儲存起來,供刪除的時候使用。
3)test_main.cpp
#include "MyString.h"
using namespace std;
int main()
{
MyString a;
cout << "【呼叫預設建構函式實現初始化】" << endl;
cout << "string a = " << a << endl;
cout << "Length = " << a.length() << endl << endl;
MyString b("123456");
cout << "【呼叫普通建構函式實現初始化】" << endl;
cout << "string b = " << b << endl;
cout << "Length = " << b.length() << endl << endl;
MyString c(b);
cout << "【呼叫拷貝建構函式實現初始化】" << endl;
cout << "string c = " << c << endl;
cout << "Length = " << c.length() << endl << endl;
MyString d = b; //這裡不會再次呼叫預設建構函式進行初始化
cout << "【呼叫 =(物件) 實現賦值】" << endl;
cout << "string d = " << d << endl;
cout << "Length = " << d.length() << endl << endl;
MyString e = "00000000";
cout << "【呼叫 =(動態指標) 實現賦值】" << endl;
cout << "string d = " << e << endl;
cout << "Length = " << e.length() << endl << endl;
MyString f = "abcdefghijklmn";
char str = f[5];
cout << "【呼叫 [] 實現索引定位輸出】" << endl;
cout << "f[5] = " << str << endl << endl;
return 0;
}