字符串类的封装常规代码头文件1234567891011121314#pragma once#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;classMyString//字符串应该是维护着一个字符数组的,在堆区{public:MyString(constchar* str);//有参构造函数MyString(constMyString str);//拷贝构造函数~MyString();//析构函数是需要的因为这个类中还维护着一个指针需要自己释放private:char* pString;//维护在堆区开辟的字符数组intm_Size;//字符串长度(不统计\0)};在头文件中定义了MyString类中应该有的属性和三个函数。有参构造函数接收字符串并创建对象拷贝构造函数可以接收同类型的对象并且复制出一个新的对象析构函数负责在释放掉本对象的同时释放掉对象中维护的指针函数实现文件123456789101112131415161718192021222324252627#define _CRT_SECURE_NO_WARNINGS 1#includemyString.h;//MyString str 123;MyString::MyString(constchar* str)//有参构造函数传进去的参数是一个字符串返回的是MyString类型的对象。{coutMyString的有参构造函数调用endl;this-pString newchar[strlen(str) 1];//给本对象的pString准备空间。strcpy(this-pString, str);//将传进来带的字符串的地址也传给本对象的pString处str是字符串不能调用pString属性。this-m_Size strlen(str);}MyString::MyString(constMyString str)//拷贝构造函数{//这个需要深拷贝因为类中有个指针。注意深拷贝是对指针进行的深拷贝,也就是会传进来个对象然后给这个对象中的指针 分配传进来的对象中的指针的大小的空间然后将这个值也赋值到本指针中。cout MyString的拷贝函数调用 endl;this-pString newchar[strlen(str.pString)1];strcpy(this-pString , str.pString);this-m_Size str.m_Size;}MyString::~MyString()//析构是需要的因为这个类中还维护着一个指针需要自己释放{cout MyString的析构函数调用 endl;if(this-pString ! NULL){delete[]this-pString;this-pString NULL;}}拷贝构造和有参构造的区别就是1有参构造传进去的是一个字符串返回成一个对象。所以要的是对象的各个属性与字符串的属性的匹配。2拷贝构造传进去的是一个对象返回的也是一个对象所以要的是传进来的对象和本对象要创建的对象之间属性的对应。3如果拷贝构造的时候发现需要拷贝个指针那么就不能直接使用编译器的拷贝构造函数了因为编译器的拷贝构造函数构造出来的对象的指针是和传进来的对象的指针是指向同一块地方的那么等到需要释放指针的时候就会出现重释放的错误。**这也是为什么需要自己重新创建拷贝构造的原因**如果类中不需要维护指针那么就不需要自己写拷贝构造自己为指针再创建空间。Test文件123456789101112#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;#include myString.h;intmain(){MyString str abc;//调用默认构造//和后面的一样MyString str(abc);MyString str2 str;//调用拷贝构造return0;}注意这里的“abc”就是传进来的字符串str然后这里的str就是创建出来的MyString类型的对象。运行的结果MyString的有参构造函数调用MyString的拷贝函数调用MyString的析构函数调用MyString的析构函数调用重载左移如果想进行coutstrendl;代码肯定会报错因为str是MyString类型的对象不认识这个。所以这个时候就需要重载一下左移运算符可以在函数文件中实现。需要用全局函数配合友元进行重载实现函数12345ostream operator(ostream cout, MyString str)//重载左移运算符{cout str.pString;//这里的pString是类中的私有属性所以需要在原类在头文件中中给整个重载函数设置友元returncout;}头文件123456classMyString{friendostream operator(ostream cout, MyString str);//设置的友元public:private:};这样cout str endl;这行代码就可以调用了。重载右移如果想进行cinstr;代码肯定也会报错因为str是MyString类型的对象不认识这个。所以这个时候就要重载一下右移运算符可以在函数文件中实现。需要用全局函数配合友元进行重载实现函数123456789101112131415161718istream operator(istream cin, MyString str)//重载右移运算符{//应该先清空原来的堆区数据if(str.pString)//这里的pString是对象中的私有属性所以需要在原类中加上这个重载函数的友元声明{delete[] str.pString;str.pString NULL;}//不用急着直接将输入的内容传给pString可以先开辟临时数组记录着输入内容。charbuf[1024];cin buf;//因为是自己重载的函数刚才将str的pString删除了现在需要重新申请空间。str.pString newchar[strlen(buf) 1];strcpy(str.pString, buf);str.m_Size strlen(buf);//别忘了还要把大小考进str的size中,因为传进来一串字符以后对象中的长度还保持着原先的长度所以需要进行修改。cout str.m_Size endl;returncin;}头文件123456classMyString//字符串应该是维护着一个字符数组的,在堆区{friendistream operator(istream cin, MyString str);public:private:};然后就能给str的pString赋值了。重载右移运算符的时候的清空原来字符串中的内容好像不太重要删除了也能正常运行。创建临时数组记录数组大小够大即可然后将赋值最后别忘了更改对象中的size。重载赋值如果想进行str2 str1直接将两个对象进行运行起来代码肯定会崩因为全拷贝了删除对象的时候会出现浅拷贝的问题。如果想进行str2 “abc直接将字符串赋值给字符串肯定也是不行的。所以需要重载两个不同参数的 运算符。一种参数是对象一种参数是字符串12MyString operator(constMyString str);MyString operator(constchar* str);返回值必须要是MyString 因为使用完运算符要返回的是自身str2. 注意在头函数中声明完了以后到实现文件中去实现的时候要写范围MyString::,而且这个类的范围需要写在返回值类型的后面函数名的前面。重载运算符与重载左移和右移运算符不同不用再像和一样使用全局函数重载了需要使用成员函数头文件1234567891011121314151617181920#pragma once#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;classMyString{friendostream operator(ostream cout, MyString str);friendistream operator(istream cin, MyString str);public:MyString(constchar* str);//有参构造函数MyString(constMyString str);//拷贝构造函数~MyString();//析构是需要的因为这个类中还维护着一个指针需要自己释放//重载两个运算符MyString operator(constMyString str);MyString operator(constchar* str);private:char* pString;//维护在堆区开辟的字符数组intm_Size;//字符串长度(不统计\0)};实现文件123456789101112131415161718192021222324252627282930#define _CRT_SECURE_NO_WARNINGS 1#includemyString.h;MyString MyString::operator(constMyString str){//先判断原堆区有没有内容如果有先释放。if(this-pString){delete[]this-pString;this-pString NULL;}//进行深拷贝this-pString newchar[strlen(str.pString) 1];strcpy(this-pString, str.pString);this-m_Size strlen(str.pString);return*this;}MyString MyString::operator(constchar* str){//先判断原堆区有没有内容如果有先释放。if(this-pString){delete[]this-pString;this-pString NULL;}//进行深拷贝this-pString newchar[strlen(str) 1];strcpy(this-pString, str);this-m_Size strlen(str);return*this;}Test文件123456789101112131415#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;#include myString.h;intmain(){MyString str abc;//调用默认构造MyString str2 bcd;str str2;MyString str3 abc;cout str endl;//bcdcout str3 endl;//abcreturn0;}重载中括号[ ]如果项进行str2[0] a;是不可以的因为[ ]不认识str。所以需要重载中括号[]。直接使用成员函数进行重载。1234567//在头文件中charoperator[](intindex);//在实现函数中charMyString::operator[](intindex)//重载中括号{returnthis-pString[index];}正常来说就返回char类型的数值就行了这样就可读了。但是如果想将str2p[1]作为运算左值来修改那么就需要返回本体char12345678910111213141516//在头文件中char operator[](intindex);//在实现函数中char MyString::operator[](intindex)//重载中括号{returnthis-pString[index];}//在Test文件中intmain(){MyString str2 bcd;cout str2[1] endl;//cstr2[1] z;cout str2[1] endl;//zreturn0;}重载加号如果想实现1234MyString str3 abc;MyString str4 def;MyString str5 str3 str4;MyString str6 str5abc;这样肯定会报错因为不认识对象,也不认识这样的字符串所以需要对进行重载使用的还是成员函数只有一个参数。从题意得传进去一个对象然后返回出一个对象或者是传进去一个字符串返回出一个对象。前提是将第一个传进去的看作是调用对象头文件12MyString operator(constMyString str);MyString operator(constchar* str);实现文件12345678910111213141516171819202122232425262728293031//重载运算符MyString MyString:: operator(constMyString str){//本身abc传入的是def刚开始应该先计算一下需要开辟的内存空间。intnewSize this-m_Size strlen(str.pString) 1;char* temp newchar[newSize];//然后将这块空间开辟出来temp指针指向它。memset(temp, 0, newSize);//将空间里面的内容全部清空。strcat(temp,this-pString);//将this-pString扔进了temp中。strcat(temp, str.pString);//然后再将str字符串扔进去这样它们就自己结合了。//但是创建好的新的字符串不能直接返回因为需要返回一个对象//所以就创建一个新的对象然后通过构造函数将字符串赋给新对象最后再返回新对象。MyString newString temp;//还有一点创建的类是空间temp用完了需要释放delete[]temp;returnnewString;}MyString MyString:: operator(constchar* str){//本身abc传入的是def刚开始应该先计算一下需要开辟的内存空间。intnewSize this-m_Size strlen(str) 1;char* temp newchar[newSize];//然后将这块空间开辟出来temp指针指向它。memset(temp, 0, newSize);//将空间里面的内容全部清空。strcat(temp,this-pString);//将this-pString扔进了temp中。strcat(temp, str);//然后再将str字符串扔进去这样它们就自己结合了。//但是创建好的新的字符串不能直接返回因为需要返回一个对象//所以就创建一个新的对象然后通过构造函数将字符串赋给新对象最后再返回新对象。MyString newString temp;//还有一点创建的类是空间temp用完了需要释放delete[]temp;returnnewString;}两种重载函数几乎一样TEST文件12345678910intmain(){MyString str3 abc;MyString str4 def;MyString str5 str3 str4;MyString str6 str5 abc;cout str5 endl;//abcdefcout str6 endl;//abcdefabcreturn0;}重载ps补充strcmp函数中如果两个字符串相等那么就返回0如果不相等那么就返回1。也是提供两种重载函数1234567891011121314151617181920212223242526272829303132333435363738//头文件//重载运算符booloperator(constMyString str);booloperator(constchar* str);//实现文件//重载运算符boolMyString::operator(constMyString str){if(strcmp(this-pString, str.pString) 0)returntrue;elsereturnfalse;}boolMyString::operator(constchar* str){if(strcmp(this-pString, str) 0)returntrue;elsereturnfalse;}//Test文件intmain(){MyString str3 abc;MyString str4 def;MyString str5 str3 str4;cout str5 endl;//abcdefif(str5 str5){cout 是相等的 endl;}else{cout 是不相等的 endl;}//结果是相等的。return0;}总结本篇文章就到这里了希望能够给你带来帮助
C++字符串类的封装你真的了解吗
字符串类的封装常规代码头文件1234567891011121314#pragma once#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;classMyString//字符串应该是维护着一个字符数组的,在堆区{public:MyString(constchar* str);//有参构造函数MyString(constMyString str);//拷贝构造函数~MyString();//析构函数是需要的因为这个类中还维护着一个指针需要自己释放private:char* pString;//维护在堆区开辟的字符数组intm_Size;//字符串长度(不统计\0)};在头文件中定义了MyString类中应该有的属性和三个函数。有参构造函数接收字符串并创建对象拷贝构造函数可以接收同类型的对象并且复制出一个新的对象析构函数负责在释放掉本对象的同时释放掉对象中维护的指针函数实现文件123456789101112131415161718192021222324252627#define _CRT_SECURE_NO_WARNINGS 1#includemyString.h;//MyString str 123;MyString::MyString(constchar* str)//有参构造函数传进去的参数是一个字符串返回的是MyString类型的对象。{coutMyString的有参构造函数调用endl;this-pString newchar[strlen(str) 1];//给本对象的pString准备空间。strcpy(this-pString, str);//将传进来带的字符串的地址也传给本对象的pString处str是字符串不能调用pString属性。this-m_Size strlen(str);}MyString::MyString(constMyString str)//拷贝构造函数{//这个需要深拷贝因为类中有个指针。注意深拷贝是对指针进行的深拷贝,也就是会传进来个对象然后给这个对象中的指针 分配传进来的对象中的指针的大小的空间然后将这个值也赋值到本指针中。cout MyString的拷贝函数调用 endl;this-pString newchar[strlen(str.pString)1];strcpy(this-pString , str.pString);this-m_Size str.m_Size;}MyString::~MyString()//析构是需要的因为这个类中还维护着一个指针需要自己释放{cout MyString的析构函数调用 endl;if(this-pString ! NULL){delete[]this-pString;this-pString NULL;}}拷贝构造和有参构造的区别就是1有参构造传进去的是一个字符串返回成一个对象。所以要的是对象的各个属性与字符串的属性的匹配。2拷贝构造传进去的是一个对象返回的也是一个对象所以要的是传进来的对象和本对象要创建的对象之间属性的对应。3如果拷贝构造的时候发现需要拷贝个指针那么就不能直接使用编译器的拷贝构造函数了因为编译器的拷贝构造函数构造出来的对象的指针是和传进来的对象的指针是指向同一块地方的那么等到需要释放指针的时候就会出现重释放的错误。**这也是为什么需要自己重新创建拷贝构造的原因**如果类中不需要维护指针那么就不需要自己写拷贝构造自己为指针再创建空间。Test文件123456789101112#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;#include myString.h;intmain(){MyString str abc;//调用默认构造//和后面的一样MyString str(abc);MyString str2 str;//调用拷贝构造return0;}注意这里的“abc”就是传进来的字符串str然后这里的str就是创建出来的MyString类型的对象。运行的结果MyString的有参构造函数调用MyString的拷贝函数调用MyString的析构函数调用MyString的析构函数调用重载左移如果想进行coutstrendl;代码肯定会报错因为str是MyString类型的对象不认识这个。所以这个时候就需要重载一下左移运算符可以在函数文件中实现。需要用全局函数配合友元进行重载实现函数12345ostream operator(ostream cout, MyString str)//重载左移运算符{cout str.pString;//这里的pString是类中的私有属性所以需要在原类在头文件中中给整个重载函数设置友元returncout;}头文件123456classMyString{friendostream operator(ostream cout, MyString str);//设置的友元public:private:};这样cout str endl;这行代码就可以调用了。重载右移如果想进行cinstr;代码肯定也会报错因为str是MyString类型的对象不认识这个。所以这个时候就要重载一下右移运算符可以在函数文件中实现。需要用全局函数配合友元进行重载实现函数123456789101112131415161718istream operator(istream cin, MyString str)//重载右移运算符{//应该先清空原来的堆区数据if(str.pString)//这里的pString是对象中的私有属性所以需要在原类中加上这个重载函数的友元声明{delete[] str.pString;str.pString NULL;}//不用急着直接将输入的内容传给pString可以先开辟临时数组记录着输入内容。charbuf[1024];cin buf;//因为是自己重载的函数刚才将str的pString删除了现在需要重新申请空间。str.pString newchar[strlen(buf) 1];strcpy(str.pString, buf);str.m_Size strlen(buf);//别忘了还要把大小考进str的size中,因为传进来一串字符以后对象中的长度还保持着原先的长度所以需要进行修改。cout str.m_Size endl;returncin;}头文件123456classMyString//字符串应该是维护着一个字符数组的,在堆区{friendistream operator(istream cin, MyString str);public:private:};然后就能给str的pString赋值了。重载右移运算符的时候的清空原来字符串中的内容好像不太重要删除了也能正常运行。创建临时数组记录数组大小够大即可然后将赋值最后别忘了更改对象中的size。重载赋值如果想进行str2 str1直接将两个对象进行运行起来代码肯定会崩因为全拷贝了删除对象的时候会出现浅拷贝的问题。如果想进行str2 “abc直接将字符串赋值给字符串肯定也是不行的。所以需要重载两个不同参数的 运算符。一种参数是对象一种参数是字符串12MyString operator(constMyString str);MyString operator(constchar* str);返回值必须要是MyString 因为使用完运算符要返回的是自身str2. 注意在头函数中声明完了以后到实现文件中去实现的时候要写范围MyString::,而且这个类的范围需要写在返回值类型的后面函数名的前面。重载运算符与重载左移和右移运算符不同不用再像和一样使用全局函数重载了需要使用成员函数头文件1234567891011121314151617181920#pragma once#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;classMyString{friendostream operator(ostream cout, MyString str);friendistream operator(istream cin, MyString str);public:MyString(constchar* str);//有参构造函数MyString(constMyString str);//拷贝构造函数~MyString();//析构是需要的因为这个类中还维护着一个指针需要自己释放//重载两个运算符MyString operator(constMyString str);MyString operator(constchar* str);private:char* pString;//维护在堆区开辟的字符数组intm_Size;//字符串长度(不统计\0)};实现文件123456789101112131415161718192021222324252627282930#define _CRT_SECURE_NO_WARNINGS 1#includemyString.h;MyString MyString::operator(constMyString str){//先判断原堆区有没有内容如果有先释放。if(this-pString){delete[]this-pString;this-pString NULL;}//进行深拷贝this-pString newchar[strlen(str.pString) 1];strcpy(this-pString, str.pString);this-m_Size strlen(str.pString);return*this;}MyString MyString::operator(constchar* str){//先判断原堆区有没有内容如果有先释放。if(this-pString){delete[]this-pString;this-pString NULL;}//进行深拷贝this-pString newchar[strlen(str) 1];strcpy(this-pString, str);this-m_Size strlen(str);return*this;}Test文件123456789101112131415#define _CRT_SECURE_NO_WARNINGS 1#includeiostreamusingnamespacestd;#include myString.h;intmain(){MyString str abc;//调用默认构造MyString str2 bcd;str str2;MyString str3 abc;cout str endl;//bcdcout str3 endl;//abcreturn0;}重载中括号[ ]如果项进行str2[0] a;是不可以的因为[ ]不认识str。所以需要重载中括号[]。直接使用成员函数进行重载。1234567//在头文件中charoperator[](intindex);//在实现函数中charMyString::operator[](intindex)//重载中括号{returnthis-pString[index];}正常来说就返回char类型的数值就行了这样就可读了。但是如果想将str2p[1]作为运算左值来修改那么就需要返回本体char12345678910111213141516//在头文件中char operator[](intindex);//在实现函数中char MyString::operator[](intindex)//重载中括号{returnthis-pString[index];}//在Test文件中intmain(){MyString str2 bcd;cout str2[1] endl;//cstr2[1] z;cout str2[1] endl;//zreturn0;}重载加号如果想实现1234MyString str3 abc;MyString str4 def;MyString str5 str3 str4;MyString str6 str5abc;这样肯定会报错因为不认识对象,也不认识这样的字符串所以需要对进行重载使用的还是成员函数只有一个参数。从题意得传进去一个对象然后返回出一个对象或者是传进去一个字符串返回出一个对象。前提是将第一个传进去的看作是调用对象头文件12MyString operator(constMyString str);MyString operator(constchar* str);实现文件12345678910111213141516171819202122232425262728293031//重载运算符MyString MyString:: operator(constMyString str){//本身abc传入的是def刚开始应该先计算一下需要开辟的内存空间。intnewSize this-m_Size strlen(str.pString) 1;char* temp newchar[newSize];//然后将这块空间开辟出来temp指针指向它。memset(temp, 0, newSize);//将空间里面的内容全部清空。strcat(temp,this-pString);//将this-pString扔进了temp中。strcat(temp, str.pString);//然后再将str字符串扔进去这样它们就自己结合了。//但是创建好的新的字符串不能直接返回因为需要返回一个对象//所以就创建一个新的对象然后通过构造函数将字符串赋给新对象最后再返回新对象。MyString newString temp;//还有一点创建的类是空间temp用完了需要释放delete[]temp;returnnewString;}MyString MyString:: operator(constchar* str){//本身abc传入的是def刚开始应该先计算一下需要开辟的内存空间。intnewSize this-m_Size strlen(str) 1;char* temp newchar[newSize];//然后将这块空间开辟出来temp指针指向它。memset(temp, 0, newSize);//将空间里面的内容全部清空。strcat(temp,this-pString);//将this-pString扔进了temp中。strcat(temp, str);//然后再将str字符串扔进去这样它们就自己结合了。//但是创建好的新的字符串不能直接返回因为需要返回一个对象//所以就创建一个新的对象然后通过构造函数将字符串赋给新对象最后再返回新对象。MyString newString temp;//还有一点创建的类是空间temp用完了需要释放delete[]temp;returnnewString;}两种重载函数几乎一样TEST文件12345678910intmain(){MyString str3 abc;MyString str4 def;MyString str5 str3 str4;MyString str6 str5 abc;cout str5 endl;//abcdefcout str6 endl;//abcdefabcreturn0;}重载ps补充strcmp函数中如果两个字符串相等那么就返回0如果不相等那么就返回1。也是提供两种重载函数1234567891011121314151617181920212223242526272829303132333435363738//头文件//重载运算符booloperator(constMyString str);booloperator(constchar* str);//实现文件//重载运算符boolMyString::operator(constMyString str){if(strcmp(this-pString, str.pString) 0)returntrue;elsereturnfalse;}boolMyString::operator(constchar* str){if(strcmp(this-pString, str) 0)returntrue;elsereturnfalse;}//Test文件intmain(){MyString str3 abc;MyString str4 def;MyString str5 str3 str4;cout str5 endl;//abcdefif(str5 str5){cout 是相等的 endl;}else{cout 是不相等的 endl;}//结果是相等的。return0;}总结本篇文章就到这里了希望能够给你带来帮助