1
前言
在笔记七十一中我们已经搭好了MyString类的基本框架,我们修改Test.cpp文件,添加两行代码:
s4=s2;
s4="ab";
#include
#include"MyString.h"
usingnamespacestd;
intmain()
{
//类定义对象时才调用构造函数
MyString s1;//调用无参构造函数
MyString s2("s2");//调用有参构造函数
MyString s3=s2;//调用拷贝构造函数深拷贝
MyString s4="abcdefg";//调用有参构造函数
s4=s2;//完全复制,指针相等引起二次析构未知bug
s4="ab";//错误未知bug
cout
system("pause");
return0;
}
运行程序,发现可以弹出dos窗口(就是那个显示输出结果的黑框),但是关闭dos窗口时软件卡顿,证明这两行代码在bug,为什么存在bug呢?目前我也不是很清楚,有一点,s4对象在定义时已经申请了一定大小的内存,后面赋值有点不合适,但具体的原因我目前不清楚,知识积累起来再写。
既然我们知道等号操作符这个地方有bug,我们就需要重载等号操作符。
2
重载等号操作符s4=s2
重载时需要分两种情形,第一种s4=s2,等号两侧都是MyString类定义的对象。调用时格式:
s4.operator=(s2)
考虑链式编程,我们需要返回一个引用,因此函数的声明就是:
MyString& operator=(const MyString& str);
注意:一般情况下我们会加const,保证目标对象的安全。
操作符重载函数为:
MyString& MyString::operator=(constMyString& str)
{
//(1)把旧的内存释放掉
if(m_p!=NULL)
{
delete[]m_p;
m_len=0;
}
//(2)根据str分配内存,str是类的对象,至少是空串
m_len=str.m_len;
m_p=newchar[m_len+1];
strcpy(m_p,str.m_p);
return*this;
}
3
重载等号操作符s4="ab"
//重载等号操作符,考虑链式编程
//s4="ab"
//s4.operator=("ab")
//MyString& operator=(const char* str)
//s4的指针已经分配内存空间了,因此需要先把旧的释放掉
MyString& MyString::operator=(constchar* str)
{
//(1)把旧的内存释放掉
if(m_p!=NULL)
{
delete[]m_p;
m_len=0;
}
//(2)根据str分配内存
if(NULL==str)
{
m_len=0;
m_p=newchar[m_len+1];
strcpy(m_p,"");
}
else
{
m_len=strlen(str);
m_p=newchar[m_len+1];
strcpy(m_p,str);
}
return*this;//支持链式编程,返回引用
}
4
MyString类重载数组[]操作符
我们定义一个字符串s4之后,想类似数组一样,输出字符串s4的某个元素,或者修改某个元素,这就需要重载数组操作符[],因为要修改字符串的某个元素,也就是说字符串数组当左值,因此需要返回一个引用。
//s4[index]
//s4.operator[](int index)
//char& operator[](int index)
完整程序:
MyString.h
#pragmaonce
classMyString
{
public:
//无参构造函数,定义一个空串
MyString(void);
//有参构造函数
MyString(constchar*p);
//拷贝构造函数
MyString(constMyString& s);
//析构函数
~MyString(void);
public:
//等号操作符重载函数s4=s2;
MyString&operator=(constMyString& str);
//等号操作符重载函数s4="ab";
MyString&operator=(constchar* str);
//重载[]操作符
char&operator[](intindex);
private:
intm_len;//储存字符串的长度
char*m_p;//指向字符串所在内存的首地址
};
MyString.cpp
#define_CRT_SECURE_NO_WARNINGS
#include
#include"MyString.h"
//无参构造函数,定义一个空串
MyString::MyString(void)
{
m_len=0;
m_p=newchar[m_len+1];
strcpy(m_p,"");
}
//有参构造函数
MyString::MyString(constchar*p)
{
if(NULL==p)
{
m_len=0;
m_p=newchar[m_len+1];
strcpy(m_p,p);
}
else
{
m_len=strlen(p);
m_p=newchar[m_len+1];
strcpy(m_p,p);
}
}
//拷贝构造函数
MyString::MyString(constMyString& s)
{
m_len=s.m_len;
m_p=newchar[m_len+1];
strcpy(m_p,s.m_p);
}
//析构函数
MyString::~MyString(void)
{
if(m_p!=NULL)
{
delete[]m_p;
m_p=NULL;
m_len=0;
}
}
//重载等号操作符,考虑链式编程
//s4=s2
//s4.operator=(s2)
//MyString& operator=(const MyString& str)
//s4的指针已经分配内存空间了,因此需要先把旧的释放掉
MyString& MyString::operator=(constMyString& str)
{
//(1)把旧的内存释放掉
if(m_p!=NULL)
{
delete[]m_p;
m_len=0;
}
//(2)根据str分配内存,str是类的对象,至少是空串
m_len=str.m_len;
m_p=newchar[m_len+1];
strcpy(m_p,str.m_p);
return*this;
}
//重载等号操作符,考虑链式编程
//s4="ab"
//s4.operator=("ab")
//MyString& operator=(const char* str)
//s4的指针已经分配内存空间了,因此需要先把旧的释放掉
MyString& MyString::operator=(constchar* str)
{
//(1)把旧的内存释放掉
if(m_p!=NULL)
{
delete[]m_p;
m_len=0;
}
//(2)根据str分配内存
if(NULL==str)
{
m_len=0;
m_p=newchar[m_len+1];
strcpy(m_p,"");
}
else
{
m_len=strlen(str);
m_p=newchar[m_len+1];
strcpy(m_p,str);
}
return*this;//支持链式编程,返回引用
}
//重载数组小标[]操作符
//s4[i]
//s4.operator[](int i)
//char& operator[](int i)
char& MyString::operator[](intindex)
{
returnm_p[index];//可以作为左值,返回引用
}
Test.cpp
#include
#include"MyString.h"
usingnamespacestd;
intmain()
{
//类定义对象时才调用构造函数
MyString s1;//调用无参构造函数
MyString s2("s2");//调用有参构造函数
MyString s3=s2;//调用拷贝构造函数深拷贝
MyString s4="abcdefg";//调用有参构造函数
s4=s2;
s4="abcde";
cout
s4[2]='f';
cout
cout
system("pause");
return0;
}
领取专属 10元无门槛券
私享最新 技术干货