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

C++字符串類的封裝你真的了解嗎

 更新時(shí)間:2022年02月14日 15:00:48   作者:是小明同學(xué)啊  
這篇文章主要為大家詳細(xì)介紹了C++字符串類的封裝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助

字符串類的封裝

常規(guī)代碼

頭文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class MyString//字符串應(yīng)該是維護(hù)著一個(gè)字符數(shù)組的,在堆區(qū)
{
public:
	MyString(const char* str);//有參構(gòu)造函數(shù)
	MyString(const MyString& str);//拷貝構(gòu)造函數(shù)
	~MyString();//析構(gòu)函數(shù)(是需要的,因?yàn)檫@個(gè)類中還維護(hù)著一個(gè)指針,需要自己釋放)
private:
	char* pString;//維護(hù)在堆區(qū)開(kāi)辟的字符數(shù)組
	int m_Size;//字符串長(zhǎng)度(不統(tǒng)計(jì)\0)
};

在頭文件中定義了MyString類中應(yīng)該有的屬性和三個(gè)函數(shù)。(有參構(gòu)造函數(shù)接收字符串并創(chuàng)建對(duì)象)(拷貝構(gòu)造函數(shù)可以接收同類型的對(duì)象并且復(fù)制出一個(gè)新的對(duì)象)(析構(gòu)函數(shù)負(fù)責(zé)在釋放掉本對(duì)象的同時(shí)釋放掉對(duì)象中維護(hù)的指針)

函數(shù)實(shí)現(xiàn)文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"myString.h";
//MyString str = "123";
MyString::MyString(const char* str)//有參構(gòu)造函數(shù),傳進(jìn)去的參數(shù)是一個(gè)字符串,返回的是MyString類型的對(duì)象。
{
	cout<<"MyString的有參構(gòu)造函數(shù)調(diào)用"<<endl;
	this->pString = new char[strlen(str) + 1];//給本對(duì)象的pString準(zhǔn)備空間。
	strcpy(this->pString, str);//將傳進(jìn)來(lái)帶的字符串的地址也傳給本對(duì)象的pString處,str是字符串,不能調(diào)用pString屬性。
	this->m_Size = strlen(str);
}
MyString::MyString(const MyString& str)//拷貝構(gòu)造函數(shù)
{
	//這個(gè)需要深拷貝,因?yàn)轭愔杏袀€(gè)指針。注意:深拷貝是對(duì)指針進(jìn)行的深拷貝,也就是會(huì)傳進(jìn)來(lái)個(gè)對(duì)象,然后給這個(gè)對(duì)象中的指針 分配傳進(jìn)來(lái)的對(duì)象中的指針的大小的空間,然后將這個(gè)值也賦值到本指針中。
	cout << "MyString的拷貝函數(shù)調(diào)用" << endl;
	this->pString = new char[strlen(str.pString)+1];
	strcpy(this->pString , str.pString);
	this->m_Size = str.m_Size;
}
MyString::~MyString()//析構(gòu)(是需要的,因?yàn)檫@個(gè)類中還維護(hù)著一個(gè)指針,需要自己釋放)
{
	cout << "MyString的析構(gòu)函數(shù)調(diào)用" << endl;
	if (this->pString != NULL)
	{
		delete[] this->pString;
		this->pString = NULL;
	}
}

拷貝構(gòu)造和有參構(gòu)造的區(qū)別就是:

1,有參構(gòu)造傳進(jìn)去的是一個(gè)字符串,返回成一個(gè)對(duì)象。所以要的是對(duì)象的各個(gè)屬性與字符串的屬性的匹配。

2,拷貝構(gòu)造傳進(jìn)去的是一個(gè)對(duì)象,返回的也是一個(gè)對(duì)象,所以要的是傳進(jìn)來(lái)的對(duì)象和本對(duì)象(要?jiǎng)?chuàng)建的對(duì)象)之間屬性的對(duì)應(yīng)。

3,如果拷貝構(gòu)造的時(shí)候發(fā)現(xiàn)需要拷貝個(gè)指針,那么就不能直接使用編譯器的拷貝構(gòu)造函數(shù)了,因?yàn)榫幾g器的拷貝構(gòu)造函數(shù)構(gòu)造出來(lái)的對(duì)象的指針是和傳進(jìn)來(lái)的對(duì)象的指針是指向同一塊地方的,那么等到需要釋放指針的時(shí)候就會(huì)出現(xiàn)重釋放的錯(cuò)誤。**(這也是為什么需要自己重新創(chuàng)建拷貝構(gòu)造的原因)**如果類中不需要維護(hù)指針,那么就不需要自己寫(xiě)拷貝構(gòu)造(自己為指針再創(chuàng)建空間)。

Test文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include "myString.h";

int main()
{
	MyString str = "abc";//調(diào)用默認(rèn)構(gòu)造
	//和后面的一樣MyString str("abc");
	MyString str2 = str;//調(diào)用拷貝構(gòu)造
	return 0;
}

注意,這里的“abc”就是傳進(jìn)來(lái)的字符串str,然后這里的str就是創(chuàng)建出來(lái)的MyString類型的對(duì)象。

運(yùn)行的結(jié)果:

MyString的有參構(gòu)造函數(shù)調(diào)用
MyString的拷貝函數(shù)調(diào)用
MyString的析構(gòu)函數(shù)調(diào)用
MyString的析構(gòu)函數(shù)調(diào)用

重載左移>>

如果想進(jìn)行

cout<<str<<endl;代碼肯定會(huì)報(bào)錯(cuò),因?yàn)閟tr是MyString類型的對(duì)象,<<不認(rèn)識(shí)這個(gè)。

所以,這個(gè)時(shí)候就需要重載一下<<左移運(yùn)算符,可以在函數(shù)文件中實(shí)現(xiàn)。(需要用全局函數(shù)配合友元進(jìn)行重載)

實(shí)現(xiàn)函數(shù):

ostream& operator<<(ostream& cout, MyString& str) //重載左移運(yùn)算符
{
	cout << str.pString;//這里的pString是類中的私有屬性,所以需要在原類(在頭文件中)中給整個(gè)重載函數(shù)設(shè)置友元
	return cout;
}

頭文件

class MyString
{
	friend ostream& operator<<(ostream& cout, MyString& str);//設(shè)置的友元
public:
private:
};

這樣cout << str << endl;這行代碼就可以調(diào)用了。

重載右移<<

如果想進(jìn)行

cin>>str;代碼肯定也會(huì)報(bào)錯(cuò),因?yàn)閟tr是MyString類型的對(duì)象,>>不認(rèn)識(shí)這個(gè)。

所以,這個(gè)時(shí)候就要重載一下>>右移運(yùn)算符,可以在函數(shù)文件中實(shí)現(xiàn)。(需要用全局函數(shù)配合友元進(jìn)行重載)

實(shí)現(xiàn)函數(shù)

istream& operator>>(istream& cin, MyString& str)//重載右移運(yùn)算符
{
	//應(yīng)該先清空原來(lái)的堆區(qū)數(shù)據(jù)
	if (str.pString)//這里的pString是對(duì)象中的私有屬性,所以需要在原類中加上這個(gè)重載函數(shù)的友元聲明
	{
		delete[] str.pString;
		str.pString = NULL;
	}
	//不用急著直接將輸入的內(nèi)容傳給pString,可以先開(kāi)辟臨時(shí)數(shù)組,記錄著輸入內(nèi)容。
	char buf[1024];
	cin >> buf;
	//因?yàn)槭亲约褐剌d的函數(shù),剛才將str的pString刪除了,現(xiàn)在需要重新申請(qǐng)空間。
	str.pString = new char[strlen(buf) + 1];
	strcpy(str.pString, buf);
	str.m_Size = strlen(buf);//別忘了還要把大小考進(jìn)str的size中,因?yàn)閭鬟M(jìn)來(lái)一串字符以后,對(duì)象中的長(zhǎng)度還保持著原先的長(zhǎng)度,所以需要進(jìn)行修改。
	cout << str.m_Size << endl;
	return cin;
}

頭文件

class MyString//字符串應(yīng)該是維護(hù)著一個(gè)字符數(shù)組的,在堆區(qū)
{
	friend istream& operator>>(istream& cin, MyString& str);
public:
private:
};

然后就能給str的pString賦值了。

重載右移運(yùn)算符的時(shí)候的清空原來(lái)字符串中的內(nèi)容好像不太重要,刪除了也能正常運(yùn)行。創(chuàng)建臨時(shí)數(shù)組記錄(數(shù)組大小夠大即可),然后將賦值,最后別忘了更改對(duì)象中的size。

重載賦值=

如果想進(jìn)行:

str2 = str1

直接將兩個(gè)對(duì)象進(jìn)行=運(yùn)行起來(lái)代碼肯定會(huì)崩,因?yàn)椋喝截惲?,刪除對(duì)象的時(shí)候會(huì)出現(xiàn)淺拷貝的問(wèn)題。

如果想進(jìn)行:

str2 = “abc"

直接將字符串賦值給字符串肯定也是不行的。

所以需要重載兩個(gè)不同參數(shù)的 = 運(yùn)算符。(一種參數(shù)是對(duì)象,一種參數(shù)是字符串)

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

返回值必須要是MyString& ,因?yàn)槭褂猛?運(yùn)算符要返回的是自身(str2). 注意在頭函數(shù)中聲明完了以后到實(shí)現(xiàn)文件中去實(shí)現(xiàn)的時(shí)候要寫(xiě)范圍MyString::,而且這個(gè)類的范圍需要寫(xiě)在返回值類型的后面,函數(shù)名的前面。

重載=運(yùn)算符,與重載左移和右移運(yùn)算符不同,不用再像<<和>>一樣使用全局函數(shù)重載了,需要使用成員函數(shù)

頭文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class MyString
{
	friend ostream& operator<<(ostream& cout, MyString& str);
	friend istream& operator>>(istream& cin, MyString& str);
public:
	MyString(const char* str);//有參構(gòu)造函數(shù)
	MyString(const MyString& str);//拷貝構(gòu)造函數(shù)
	~MyString();//析構(gòu)(是需要的,因?yàn)檫@個(gè)類中還維護(hù)著一個(gè)指針,需要自己釋放)
	//重載兩個(gè)=運(yùn)算符
	MyString& operator=(const MyString& str);
	MyString& operator=(const char* str);

private:
	char* pString;//維護(hù)在堆區(qū)開(kāi)辟的字符數(shù)組
	int m_Size;//字符串長(zhǎng)度(不統(tǒng)計(jì)\0)
};

實(shí)現(xiàn)文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"myString.h";
MyString & MyString::operator=(const MyString & str)
{
	//先判斷原堆區(qū)有沒(méi)有內(nèi)容,如果有先釋放。
	if (this->pString)
	{
		delete[]this->pString;
		this->pString = NULL;
	}
	//進(jìn)行深拷貝
	this->pString = new char[strlen(str.pString) + 1];
	strcpy(this->pString, str.pString);
	this->m_Size = strlen(str.pString);
	return *this;
}
MyString & MyString::operator=(const char* str)
{
	//先判斷原堆區(qū)有沒(méi)有內(nèi)容,如果有先釋放。
	if (this->pString)
	{
		delete[]this->pString;
		this->pString = NULL;
	}
	//進(jìn)行深拷貝
	this->pString = new char[strlen(str) + 1];
	strcpy(this->pString, str);
	this->m_Size = strlen(str);
	return *this;
}

Test文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include "myString.h";

int main()
{
	MyString str = "abc";//調(diào)用默認(rèn)構(gòu)造
	MyString str2 = "bcd";
	str = str2;
	MyString str3 = "abc";
	cout << str << endl;//bcd
	cout << str3 << endl;//abc
	return 0;
}

重載中括號(hào)[ ]

如果項(xiàng)進(jìn)行

str2[0] = 'a';

是不可以的,因?yàn)閇 ]不認(rèn)識(shí)str。

所以需要重載中括號(hào)[]。直接使用成員函數(shù)進(jìn)行重載。

//在頭文件中:
char operator[](int index);
//在實(shí)現(xiàn)函數(shù)中:
char MyString::operator[](int index)//重載中括號(hào)
{
	return this->pString[index];
}

正常來(lái)說(shuō)就返回char類型的數(shù)值就行了,這樣就可讀了。

但是如果想將str2p[1]作為運(yùn)算左值來(lái)修改,那么就需要返回本體char&

//在頭文件中:
char& operator[](int index);
//在實(shí)現(xiàn)函數(shù)中:
char& MyString::operator[](int index)//重載中括號(hào)
{
	return this->pString[index];
}
//在Test文件中
int main()
{
	MyString str2 = "bcd";
	cout << str2[1] << endl;//c
	str2[1] = 'z';
	cout << str2[1] << endl;//z
	return 0;
}

重載加號(hào)+

如果想實(shí)現(xiàn):

MyString str3 = "abc";
MyString str4 = "def";
MyString str5 = str3 + str4;
MyString str6 = str5+"abc";

這樣肯定會(huì)報(bào)錯(cuò),因?yàn)?不認(rèn)識(shí)對(duì)象,也不認(rèn)識(shí)這樣的字符串

所以,需要對(duì)+進(jìn)行重載,使用的還是成員函數(shù),只有一個(gè)參數(shù)。

從題意得,傳進(jìn)去一個(gè)對(duì)象,然后返回出一個(gè)對(duì)象,或者是傳進(jìn)去一個(gè)字符串,返回出一個(gè)對(duì)象。(前提是將第一個(gè)傳進(jìn)去的看作是調(diào)用對(duì)象)

頭文件

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

實(shí)現(xiàn)文件

//重載+運(yùn)算符
MyString MyString:: operator+(const MyString& str)
{
	//本身abc,傳入的是def,剛開(kāi)始應(yīng)該先計(jì)算一下需要開(kāi)辟的內(nèi)存空間。
	int newSize = this->m_Size + strlen(str.pString) + 1;
	char* temp = new char[newSize];//然后將這塊空間開(kāi)辟出來(lái),temp指針指向它。
	memset(temp, 0, newSize);//將空間里面的內(nèi)容全部清空。
	strcat(temp, this->pString);//將this->pString扔進(jìn)了temp中。
	strcat(temp, str.pString);//然后再將str字符串扔進(jìn)去,這樣它們就自己結(jié)合了。
	//但是創(chuàng)建好的新的字符串不能直接返回,因?yàn)樾枰祷匾粋€(gè)對(duì)象
	//所以就創(chuàng)建一個(gè)新的對(duì)象,然后通過(guò)構(gòu)造函數(shù)將字符串賦給新對(duì)象,最后再返回新對(duì)象。
	MyString newString = temp;
	//還有一點(diǎn),創(chuàng)建的類是空間temp用完了需要釋放
	delete[]temp;
	return newString;	
}
MyString MyString:: operator+(const char* str)
{
	//本身abc,傳入的是def,剛開(kāi)始應(yīng)該先計(jì)算一下需要開(kāi)辟的內(nèi)存空間。
	int newSize = this->m_Size + strlen(str) + 1;
	char* temp = new char[newSize];//然后將這塊空間開(kāi)辟出來(lái),temp指針指向它。
	memset(temp, 0, newSize);//將空間里面的內(nèi)容全部清空。
	strcat(temp, this->pString);//將this->pString扔進(jìn)了temp中。
	strcat(temp, str);//然后再將str字符串扔進(jìn)去,這樣它們就自己結(jié)合了。
	//但是創(chuàng)建好的新的字符串不能直接返回,因?yàn)樾枰祷匾粋€(gè)對(duì)象
	//所以就創(chuàng)建一個(gè)新的對(duì)象,然后通過(guò)構(gòu)造函數(shù)將字符串賦給新對(duì)象,最后再返回新對(duì)象。
	MyString newString = temp;
	//還有一點(diǎn),創(chuàng)建的類是空間temp用完了需要釋放
	delete[]temp;
	return newString;
}

兩種+重載函數(shù)幾乎一樣

TEST文件

int main()
{
	MyString str3 = "abc";
	MyString str4 = "def";
	MyString str5 = str3 + str4;
	MyString str6 = str5 + "abc";
	cout << str5 << endl;//abcdef
	cout << str6 << endl;//abcdefabc
	return 0;
}

重載==

ps補(bǔ)充:strcmp函數(shù)中,如果兩個(gè)字符串相等,那么就返回0,如果不相等,那么就返回1。

也是提供兩種重載函數(shù):

//頭文件:
//重載==運(yùn)算符
bool operator==(const MyString& str);
bool operator==(const char* str);
//實(shí)現(xiàn)文件:
//重載==運(yùn)算符
bool MyString::operator==(const MyString & str)
{
	if (strcmp(this->pString, str.pString) == 0)
		return true;
	else
		return false;
}
bool MyString::operator==(const char* str)
{
	if (strcmp(this->pString, str) == 0)
		return true;
	else
		return false;
}
//Test文件
int main()
{
	MyString str3 = "abc";
	MyString str4 = "def";
	MyString str5 = str3 + str4;
	cout << str5 << endl;//abcdef
	if (str5 == str5)
	{
		cout << "是相等的" << endl;
	}
	else
	{
		cout << "是不相等的" << endl;
	}
	//結(jié)果是相等的。
	return 0;
}

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容! 

相關(guān)文章

  • mysate中stat命令的實(shí)現(xiàn)方法

    mysate中stat命令的實(shí)現(xiàn)方法

    這篇文章主要介紹了mysate中stat命令的實(shí)現(xiàn)方法,stat作用:用來(lái)顯示文件的詳細(xì)信息,包括inode, atime, mtime, ctime,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • Opencv二幀差法檢測(cè)運(yùn)動(dòng)目標(biāo)與提取輪廓

    Opencv二幀差法檢測(cè)運(yùn)動(dòng)目標(biāo)與提取輪廓

    這篇文章主要為大家詳細(xì)介紹了Opencv使用二幀差法檢測(cè)運(yùn)動(dòng)目標(biāo)與提取輪廓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • STL 的string類怎么啦

    STL 的string類怎么啦

    在我們研究string類犯了什么毛病之前,還讓我先說(shuō)一下如何了解一個(gè)C++的類。我們要了解一個(gè)C++的類,一般來(lái)說(shuō),要從三個(gè)方面入手
    2013-11-11
  • C++之異常處理詳解

    C++之異常處理詳解

    C++中處理異常的過(guò)程是這樣的:在執(zhí)行程序發(fā)生異常,可以不在本函數(shù)中處理,而是拋出一個(gè)錯(cuò)誤信息,把它傳遞給上一級(jí)的函數(shù)來(lái)解決,上一級(jí)解決不了,再傳給其上一級(jí),由其上一級(jí)處理
    2013-08-08
  • C語(yǔ)言實(shí)現(xiàn)貪吃蛇小黑窗

    C語(yǔ)言實(shí)現(xiàn)貪吃蛇小黑窗

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)貪吃蛇小黑窗,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • ros項(xiàng)目調(diào)試:vscode下配置開(kāi)發(fā)ROS項(xiàng)目的詳細(xì)教程

    ros項(xiàng)目調(diào)試:vscode下配置開(kāi)發(fā)ROS項(xiàng)目的詳細(xì)教程

    這篇文章主要介紹了ros項(xiàng)目調(diào)試:vscode下配置開(kāi)發(fā)ROS項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • C語(yǔ)言經(jīng)典算法例題求100-999之間的“水仙花數(shù)”

    C語(yǔ)言經(jīng)典算法例題求100-999之間的“水仙花數(shù)”

    本文的主要內(nèi)容,設(shè)計(jì)一個(gè)程序,找出100-999之間的“水仙花數(shù)”,需要的朋友可以參考下
    2015-07-07
  • C++實(shí)現(xiàn)旋轉(zhuǎn)掃描儀的示例代碼

    C++實(shí)現(xiàn)旋轉(zhuǎn)掃描儀的示例代碼

    旋轉(zhuǎn)掃描儀(Rotating?Scanner),也稱為旋轉(zhuǎn)掃描儀或圓形掃描儀,是一種用于獲取圖像和文檔的設(shè)備,下面就跟隨小編一起來(lái)學(xué)習(xí)一下如何使用C++實(shí)現(xiàn)旋轉(zhuǎn)掃描儀功能吧
    2024-02-02
  • C語(yǔ)言清除scanf()緩存的案例講解

    C語(yǔ)言清除scanf()緩存的案例講解

    今天小編就為大家分享一篇關(guān)于C語(yǔ)言清除scanf()緩存的案例講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • C語(yǔ)言變長(zhǎng)數(shù)組 struct中char data[0]的用法詳解

    C語(yǔ)言變長(zhǎng)數(shù)組 struct中char data[0]的用法詳解

    下面小編就為大家?guī)?lái)一篇C語(yǔ)言變長(zhǎng)數(shù)組 struct中char data[0]的用法詳解。小編覺(jué)得挺不錯(cuò)的現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01

最新評(píng)論