通过对string类构造、拷贝构造、赋值、操作符函数的实现及调试,可以更加深刻的认识在创建或修改对象内容时的调用关系。下面是简单的实现:
Mystr类:
- class Mystr{
- public:
- Mystr(void);
- Mystr(const char *str);//加*str=NULL可代替无参构造函数
- Mystr(const Mystr &other);
- Mystr & operator=(const Mystr &other);
- Mystr & operator+=(const Mystr &other);
- Mystr & operator+(const Mystr &other);
- ~Mystr(void);
- void print_str();
- private:
- char *m_data;
- };
函数定义:
- /*构造函数1*/
- Mystr::Mystr(void){
- // cout<<"constructor 1"<<endl;
- m_data=new char[1];
- *m_data='\0';
- }
- /*构造函数2*/
- Mystr::Mystr(const char *str){
- if(str==NULL){
- // cout<<"constructor 2 NULL"<<endl;
- m_data=new char[1];
- *m_data='\0';
- }
- else{
- // cout<<"constructor 2"<<endl;
- m_data=new char[strlen(str)+1];
- assert(m_data);
- strcpy(m_data, str);
- }
- }
- /*拷贝构造函数*/
- Mystr::Mystr(const Mystr &other){
- // cout<<"copy constructor"<<endl;
- m_data=new char[strlen(other.m_data)+1];
- assert(m_data);
- strcpy(m_data, other.m_data);
- }
- /*赋值函数*/
- Mystr& Mystr::operator=(const Mystr &other){
- // cout<<"operator="<<endl;
- if(this==&other){//避免自身赋值
- // cout<<"self"<<endl;
- return *this;
- }
- else{
- delete [] m_data;
- m_data=new char[strlen(other.m_data)+1];
- assert(m_data);
- strcpy(m_data, other.m_data);
- }
- return *this;
- }
- /*操作符+=函数*/
- Mystr& Mystr::operator+=(const Mystr &other){
- // cout<<"operator+="<<endl;
- int len=strlen(m_data)+strlen(other.m_data);
- char *t=new char[len+1];
- assert(t);
- strcpy(t, m_data);
- strcat(t, other.m_data);
- if(m_data) delete [] m_data;
- m_data=t;
- return *this;
- }
- /*操作符+函数重载*/
- Mystr& Mystr::operator+(const Mystr &other){
- // cout<<"operator+"<<endl;
- int len=strlen(m_data)+strlen(other.m_data);
- char *t=new char[len+1];
- assert(t);
- strcpy(t, m_data);
- strcat(t, other.m_data);
- if(m_data) delete [] m_data;
- m_data=t;
- return *this;
- }
- /*析构函数*/
- Mystr::~Mystr(void){
- delete [] m_data;
- }
- /*普通成员函数*/
- void Mystr::print_str(){
- cout<<this->m_data<<endl;
- }
测试用例:
- void main(){
- Mystr s0;//构造1
- Mystr s1("123abc");//构造2
- Mystr s2="DEF";//构造2
- Mystr s3=s2;//拷贝
- s0=s1;//赋值
- s0+s1;//操作符+
- s0+=s1;//操作符+=
- s0.print_str();
- Mystr s4(NULL);//构造2
- s4=s1+"_XXX";//调用3个函数:构造2(for"_XXX"),操作符+,操作符=
- s4.print_str();
- s4=s3+s2;//不同于s4=s1+"_XXX",仅调用2个函数:操作符+,操作符=
- s4.print_str();
- //s4="aaa"+"bbb";//错误,为什么, ans: +没有重载两个常量操作符
- Mystr s5=s4+"_qqq";//调用3个函数:构造2,操作符+,拷贝
- s5.print_str();
- }
实现注意事项:
1 free或delete 空指针是没问题的, 但野指针或者指向只读内存区的指针会出问题
2 下面第二句会出现内存错误
char *m="111";
delete [] m;//问题在这
m=NULL;
delete [] m;
3 strlen(NULL)的实现中没检查空指针NULL,因此会出内存错误
4 Mystr str;
实现时,不赋初值默认为空字符'\0',不要NULL防止再次访问str时出内存错误,比如strlen(m_data)和访问
5 构造函数无返回值
6 构造函数不能为虚函数,而析构函数可以