文章目录

  • 第一步:构建简单的构造函数和析构函数
    • 1.1 模拟输出(operator<<)
      • 为了避免使用友元:在类外在定义再写一个输出函数:
    • 1.2 拷贝构造函数
    • 1.3 赋值运算符重载
    • 1.4 加法运算符重载
      • 1.4.1对象和对象相加
      • 1.4.2字符串和对象相加
    • 1.5 移动构造函数
    • 1.6 移动赋值运算符重载在整个程序执行的过程中,只对堆内存空间new了一次,
  • **重点**:
    • 重点:
      • 完整代码:

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

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->strif (str != NULL){out << str;   }return out;}

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

ostream& operator<<(ostream& out,const String &s)
{                            //类外没有this指针,需要在定义一个对象ss << 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;
}
```cppint 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->strif (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指针,需要在定义一个对象ss << 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;
}

【C++】使用类来模拟string相关推荐

  1. 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现

    内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...

  2. String类的模拟实现

    目录: 一.经典String类的问题 1,浅拷贝 2,深拷贝 二.现代写法版的string类 三.传统String类的模拟实现 1.迭代器 2.operator[] 3.size() 4.c_str( ...

  3. C++关于string类的模拟实现

    文章目录 一.string类的模拟实现 1.成员变量 2.构造函数 (1)无参构造函数 (2)有参构造函数 3.c_str函数 4.operator[] 5.深浅拷贝问题 (1)浅拷贝 (2)深拷贝 ...

  4. Java黑皮书课后题第10章:**10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级

    **10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级 题目 程序 代码 Test7.java Test7_Account.java 运行示例 题目 程序 Tes ...

  5. java定义计算机类并模拟其操作

    java定义计算机类并模拟其操作 /*** 定义计算机类并模拟其操作*/ public class Computer {//成员变量private String cpu = "Intel&q ...

  6. java面向对象第一课,定义类,模拟人的行为:吃饭工作休息

    java面向对象第一课,定义类,模拟人的行为:吃饭工作休息 /*** 定义类,模拟人的行为:吃饭工作休息*/ public class Person {//静态特征:成员变量 属性 fieldStri ...

  7. 重学JavaSE 第11章 : 常用类API、String、日期API、比较器、BigDecimal、System等

    文章目录 一.字符串相关的类 1.1.String类的概述 1.2.理解String的不可变性 1.3.String不同实例化方式的对比 1.4.String不同拼接操作的对比 1.4.1.Strin ...

  8. 【蓝桥】第十一届软件类校内模拟赛(一)

    前言 本题解为第十一届软件类校内模拟赛个人题解,但非官方满分题解,因此,可能存在下列问题 题意理解错误,导致答案错误. 代码中存在一些问题,导致答案错误. 算法复杂度的分析有误,导致不能在规定时间内得 ...

  9. Java储蓄账户类及测试类,模拟存款

    老师布置了一个实验题:编写储蓄账户类及测试类,模拟存款,参考以下运行方式: 1.新开5个储蓄账户,各储蓄账户的编号.户名在新开储蓄账户时初始化,假设每位用户新开储蓄账户时都存入了一笔钱. 2.提示用户 ...

  10. java模拟使用接口,关于java:模拟一个类与模拟它的接口

    对于单元测试,我需要模拟几个依赖项.依赖项之一是实现接口的类: public class DataAccessImpl implements DataAccess { ... } 我需要设置一个这个类 ...

最新文章

  1. ​超大规模时空数据的分布式存储与应用
  2. 检查字符串是否包含数字
  3. element ui分页怎么做_element ui里面table分页,页数从0开始的怎么做?
  4. Android震动vibrator系统开发全过程
  5. python tqdm自定义更新进度条
  6. arcgis api for javascript中使用proxy.jsp
  7. 【面试】iOS 开发面试题(二)
  8. python的函数调用_三个案例带你了解python回调函数
  9. html条纹填充色,HTML5/Canvas 上传图片的彩色斑马条纹遮罩效果
  10. canvas学习笔记-贝塞尔曲线
  11. qfileinfolist 取中间_公司起名:网络公司名字起名寓意如何取寓意成功的网络公司名字...
  12. steam一键授权工具_超实用小工具!一键将PC其它平台的游戏导入Steam
  13. 基于ThinkPHP5+MySQL的超市进销存管理系统
  14. 时不变线性系统和时变线性系统方程的对角化
  15. 弹性均质圆环法计算过程_盾构隧道衬砌管片计算方法的比较
  16. 微型计算机偏移地址,请高手讲解一下在微机原理里面,偏移地址,段地址,实体地址之间的关系!配合图解更好,谢谢!...
  17. 计算机节能+关闭硬盘,优化三:CPU节能关闭_固态硬盘-中关村在线
  18. Programming Rust Fast, Safe Systems Development(译) 引用(第五章 完)
  19. 职场人士需了解:职场文件删除了三种恢复方法
  20. win10,win11后在cmd命令行输入python自动调用微软应用商店

热门文章

  1. Python注释符号(多行注释和单行注释)用法详解
  2. ionic介绍以及ionic环境搭建
  3. 从头开始阅读PyTorch代码 -- Operators篇
  4. 网页或大屏展示的倒计时器
  5. 775针服务器cpu性能排行,CPU性能排行榜各种cup应有尽有
  6. HCIA-IoT 个人学习总结 Day2
  7. 详解WIFI能用但是电脑不能上网怎么解决
  8. 上传图片到淘宝 API
  9. requests库手工识别验证码登录超星泛雅
  10. PHP实现文章评论系统