【C++】使用类来模拟string

第一步:构建简单的构造函数和析构函数

class String
{
private:
    char* str;
public:
    String(char* p, int)
    {
        str = p;
    }
    //构造函数
    String(const char* p = NULL) :str(NULL)
    {
        if (p != NULL)//要传的字符串不为空
        {
            //申请堆空间
            str = new char[strlen(p) + 1];
            strcpy_s(str, strlen(p) + 1, p);
        }
        else
        {
            str = new char[1];
            *str = '\0';
        }
        cout << "Create String:" << this << endl;
    }
     //析构函数
    ~String()
    {
        if (str != NULL)
        {
            delete[]str;
        }
        str = NULL;
        cout << "Destory String" << this << endl;
    }
};

1.1 模拟输出(operator<<)

避免友元函数,需要在类外写一个输出函数

   ostream& operator<<(ostream& out)const
    {  //this->str
        if (str != NULL)
        {
            out << str;   
        }
        return out;
    }

为了避免使用友元:在类外在定义再写一个输出函数:

ostream& operator<<(ostream& out,const String &s)
{                            //类外没有this指针,需要在定义一个对象s
        s << out;  //<<调用类中的 s.operator<<() 
        return out;
  
}

int main()
{
   String s{ "baiU" };
   cout << s << endl;//直接调用输出运算符,输出对象
}

请添加图片描述

1.2 拷贝构造函数

String(const String& s)
    {
        //避免浅拷贝
        str = new char[strlen(s.str) + 1];;
        strcpy_s(str, strlen(s.str) + 1, s.str);
        cout << "copy String" << this << endl;
    }
int main()
{
   String s{ "baiU" };
   String s1(s);
}

请添加图片描述

1.3 赋值运算符重载

String& operator = (const String& s)
    {
        if (this != &s)
        {
            delete[]str;
            str = new char[strlen(s.str) + 1];
            strcpy_s(str, strlen(s.str) + 1, s.str);
        }
        cout << "operator =" << this << endl;
        return *this;
    }

注意点:防止自赋值,防止内存泄漏,防止浅拷贝

int main()
{
   String s{ "baiU" };
   String s1(s);
   String s2{"shiqianyu"};
   s2 = s;
}

请添加图片描述

1.4 加法运算符重载

因为返回时要构造一个对象,需要在重载一个构造函数,作为私有成员。

 String(char* p, int)//int 占位符
    {
        str = p;
    }

1.4.1对象和对象相加

 String operator+(const String& s)
    {
        int len = strlen(str) + strlen(s.str) + 1;
        char* p = new char[len];
        strcpy_s(p, len, str);
        strcat_s(p,len,s.str);
        cout << "Object+object" << endl;
        return String(p, 1);
    }

1.4.2字符串和对象相加

String operator+(const char* p, const String& s)
{
    cout << "char* + Object" << endl;
    return String(p) + s;
}
int main()
{
   String s{ "baiU" };
   String s2{"shiqianyu"};
    s = s + s2;
  //  s2 = "love" + s2;
    String s3;
    s3 = fun();
    return 0;
}

请添加图片描述

1.5 移动构造函数

String(String&&s)
    {
        cout << "move construct:" << this<<endl;
        str = s.str;
        s.str = NULL;
    }

1.6 移动赋值运算符重载在整个程序执行的过程中,只对堆内存空间new了一次,

String fun()
{
    String s2("yangyu");
    return s2;
}
```cpp
  int main()
{
    String s1;  //调用默认构造申请对象空间
    s1 = fun();
    return 0;
}
  1. String s1;

调用构造函数申请对象空间
请添加图片描述
2. String s2{yangyu}; 调用构造函数,申请空间,创建对象,并对对象进行初始化。
请添加图片描述
3. return s2
调用移动构造函数,创建将亡值对象,并让将亡值对象指向s2.(str = s.str;)。并把s2中str置为空(s.str = NULL;)
请添加图片描述
4. 析构s2
请添加图片描述
5. s1 = fun() 调用Release()完成数据交换。 s.str = Release(s.str);·请添加图片描述

重点

  1. 首先s2调用构造函数完成对str的初始化,也就是s2指向为字符串“baiU”开辟的堆空间。
  2. return s2时,返回调用点处调用的是移动构造函数)创建将亡值对象,指向 s2申请的空间,
  3. s2析构。
  4. 将亡值移动赋值给s1过程。

请添加图片描述

char* Release(char* p)
    {
        char* old = str;
        str = p;
        return old;
    }

重点:

Release()函数实现了资源的交换,让s1指向s2申请的空间,将亡值指向s1申请的空间,函数结束。将亡值值被析构,s1成功拿到了原s2的资源,

    //优先调用
    String& operator = (String&&s)
    {
        if (this != &s)
        {
            s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。
        }
        cout << "operator =&&" << this << endl;
        return *this;
    }

完整代码:

class String
{
private:
    char* str;
public:
    String(char* p, int)
    {
        str = p;
    }
    //构造函数
    String(const char* p = NULL) :str(NULL)
    {
        if (p != NULL)//要传的字符串不为空
        {
            //申请堆空间
            str = new char[strlen(p) + 1];
            strcpy_s(str, strlen(p) + 1, p);
        }
        else
        {
            str = new char[1];
            *str = '\0';
        }
        cout << "Create String:" << this << endl;
    }
    //拷贝构造函数
    String(const String& s)
    {
        //避免浅拷贝
        str = new char[strlen(s.str) + 1];;
        strcpy_s(str, strlen(s.str) + 1, s.str);
        cout << "copy String" << this << endl;
    }
    //移动构造函数
    String(String&&s)
    {
        cout << "move construct:" << this<<endl;
        str = s.str;
        s.str = NULL;
    }

    //析构函数
    ~String()
    {
        if (str != NULL)
        {
            delete[]str;
        }
        str = NULL;
        cout << "Destory String" << this << endl;
    }
    //避免友元函数,需要在类外写一个输出函数
    ostream& operator<<(ostream& out)const
    {  //this->str
        if (str != NULL)
        {
            out << str;   
        }
        return out;
    }
    //赋值运算符重载
    String& operator = (const String& s)
    {
        if (this != &s)
        {
            delete[]str;
            str = new char[strlen(s.str) + 1];
            strcpy_s(str, strlen(s.str) + 1, s.str);
        }
        cout << "operator =" << this << endl;
        return *this;
    }
    char* Release(char* p)
    {
        char* old = str;
        str = p;
        return old;
    }
    //优先调用
    String& operator = (String&&s)
    {
        if (this != &s)
        {
            s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。
        }
        cout << "operator =&&" << this << endl;
        return *this;
    }
    //加法运算符重载
    //对象和对象相加

    String operator+(const String& s)
    {
        int len = strlen(str) + strlen(s.str) + 1;
        char* p = new char[len];
        strcpy_s(p, len, str);
        strcat_s(p,len,s.str);
        cout << "Object+object" << endl;
        return String(p, 1);
    }
   
    
};
String fun()
{
    String s2("yangyu");
    return s2;
}

ostream& operator<<(ostream& out,const String &s)
{                            //类外没有this指针,需要在定义一个对象s
        s << out;  //<<调用类中的 s.operator<<() 
        return out;
  
}
String operator+(const char* p, const String& s)
{
    cout << "char* + Object" << endl;
    return String(p) + s;
}
int main()
{
   // String s{ "baiU" };
   // cout << s << endl;//直接调用输出运算符,输出对象s
   // String s1(s);
   // String s2{"shiqianyu"};
   // s2 = s;
    s = s + s2;
  //  s2 = "love" + s2;
    String s3;
    s3 = fun();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值