c++参考std::string自己设计类hstring

2024-06-18 23:04

本文主要是介绍c++参考std::string自己设计类hstring,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、前言

二、设计需求

三、设计思想

1.功能一

1.功能二

四、设计过程

1.类hstring搭建

2. 实现有参构造函数

3. 实现副本构造函数

4.完整代码

五、结束语


一、前言

        在c++中有很多的库,但是在有些时候呢,我们一定要学会自己去设计库,不要老用别人的东西,比方说这个东西方便吗?特别方便。但是这个东西呢,有很大的副作用。

        再比方说一些特种项目,你比方说木马病毒啊,然后外挂等等,这种工程里你如果用这样的std::string去做的话,那么它带来的后果是很恶劣的,很可怕的,在这种情况下我怎么做呢?我一般推荐大家是我自己去写一个轻量级的这种字符串类型的库,所以今天我们不学其他的知识点,主要是自己设计一个简单的库。

二、设计需求

        我们要设计的项目设计需求比较简单,主要实现简单的功能即可,具体项目功能设计如图:

三、设计思想

        我们要设计一个类hsting,就参考这个std::string设计,我们主要不多做,不贪心,我们主要做两个功能。

1.功能一

        第一个功能是实现 hstring str("你好!"); 它是一个构造函数,其中传递了一个const char* 类型的字符串 "你好!" 。所以根据分析,我们类hstring中要有一个私有成员变量为char* 类型的成员变量m_str用来展现字符串。

        但是我们的m_str赋值操作不能够直接进行赋值,比如:

m_str = str; // str 为形参const char* str

 这种写法会直接报错显示:不能将"const char *"类型的值分配到"char *"类型的实体。

        所以我们要为m_str申请一块动态的内存空间,空间大小为传递来的r的大小。这里需要在hstring中添加一个成员变量unsigned short len表示str的字节大小。同时需要设计函数getLen()获取str的字节大小。

1.功能二

        功能二为hstring strA(str) // 副本构造函数,参数为创造声明的示例str,功能二实现与功能一内容思想基本相似,同时需要注意这里同样也不能够直接赋值:

       这是因为m_str为char*类型的指针,存储的是地址。如果直接赋值会导致实例str与strA中的成员变量m_str存储相同的地址,在析构函数中会重复析构两次,导致程序崩溃!

 代码和结果展示:

    // 打印地址printf("%p\n", str.getStr());printf("%p\n", strA.getStr());

四、设计过程

1.类hstring搭建

        前期类hstring搭建比较简单,主要是添加简单的成员变量和构造函数初始化功能。

class hstring
{
public:// 成员变量初始化hstring(){m_str = new char[1]{0};len = 0;}  // 获取lenunsigned short getLen() const{return len;}// 获取 m_strchar* getStr() const{return m_str;}// 析构函数:释放内存~hstring(){delete[] m_str;}private:char* m_str;unsigned short len;
};
2. 实现有参构造函数

        主要实现步骤为:

1. 设计获取char字节长度的函数返回值为len

2.为m_str动态申请内存空间,长度为len

3.用c语言中的memcpy功能库,进行内存拷贝操作

代码如下:

// 有参构造函数hstring(const char* str) {len = getLen(str);m_str = new char[len];memcpy(m_str, str, len);}// 获取形参的字节长度unsigned short getLen(const char* hstring){while (hstring[this->len++]);return len;}
3. 实现副本构造函数

        与有参构造结构相似

    // 副本构造函数hstring(const hstring& hstr){//m_str = hstr.m_str; !!! 错误写法len = getLen(hstr.getStr());m_str = new char[len];memcpy(m_str, hstr.getStr(), len);}// 第二种写法//hstring(const hstring& T): hstring(T.getStr()) {}
4.完整代码
#include <iostream>class hstring
{
private:char* m_str;unsigned short len; // 存储字节大小
public:// 成员变量初始化hstring(){m_str = new char[1]{0};len = 0;}// 有参构造函数hstring(const char* str) {len = getLen(str);m_str = new char[len];memcpy(m_str, str, len);}// 副本构造函数hstring(const hstring& hstr){//m_str = hstr.m_str; !!! 错误写法len = getLen(hstr.getStr());m_str = new char[len];memcpy(m_str, hstr.getStr(), len);}// 第二种写法//hstring(const hstring& T): hstring(T.getStr()) {}// 获取形参的字节长度unsigned short getLen(const char* hstring){while (hstring[this->len++]);return len;}// 重新赋值操作void setStr(const char* hstring){// 先删除地址delete[] m_str;len = getLen(hstring);m_str = new char[len];memcpy(m_str, hstring, len);}// 获取lenunsigned short getLen() const{return len;}// 获取 m_strchar* getStr() const{return m_str;}// 析构函数:释放内存~hstring(){delete[] m_str;}};
int main()
{hstring str("你好!");  // 构造函数hstring strA(str);      // 副本构造函数// 打印地址printf("%p\n", str.getStr());  printf("%p\n", strA.getStr());}

五、结束语

        自定义类hstring只是一个小的练习,里面的功能十分有限,到后面我还会持续的更新hstring的完整版,还请各位彦祖们多多支持!!!

这篇关于c++参考std::string自己设计类hstring的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073306

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

C++的模板(八):子系统

平常所见的大部分模板代码,模板所传的参数类型,到了模板里面,或实例化为对象,或嵌入模板内部结构中,或在模板内又派生了子类。不管怎样,最终他们在模板内,直接或间接,都实例化成对象了。 但这不是唯一的用法。试想一下。如果在模板内限制调用参数类型的构造函数会发生什么?参数类的对象在模板内无法构造。他们只能从模板的成员函数传入。模板不保存这些对象或者只保存他们的指针。因为构造函数被分离,这些指针在模板外

C++工程编译链接错误汇总VisualStudio

目录 一些小的知识点 make工具 可以使用windows下的事件查看器崩溃的地方 dumpbin工具查看dll是32位还是64位的 _MSC_VER .cc 和.cpp 【VC++目录中的包含目录】 vs 【C/C++常规中的附加包含目录】——头文件所在目录如何怎么添加,添加了以后搜索头文件就会到这些个路径下搜索了 include<> 和 include"" WinMain 和

C/C++的编译和链接过程

目录 从源文件生成可执行文件(书中第2章) 1.Preprocessing预处理——预处理器cpp 2.Compilation编译——编译器cll ps:vs中优化选项设置 3.Assembly汇编——汇编器as ps:vs中汇编输出文件设置 4.Linking链接——链接器ld 符号 模块,库 链接过程——链接器 链接过程 1.简单链接的例子 2.链接过程 3.地址和

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型

在线装修管理系统的设计

管理员账户功能包括:系统首页,个人中心,管理员管理,装修队管理,用户管理,装修管理,基础数据管理,论坛管理 前台账户功能包括:系统首页,个人中心,公告信息,论坛,装修,装修队 开发系统:Windows 架构模式:B/S JDK版本:Java JDK1.8 开发工具:IDEA(推荐) 数据库版本: mysql5.7 数据库可视化工具: navicat 服务器:SpringBoot自带 ap

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使

DDei在线设计器-API-DDeiSheet

DDeiSheet   DDeiSheet是代表一个页签,一个页签含有一个DDeiStage用于显示图形。   DDeiSheet实例包含了一个页签的所有数据,在获取后可以通过它访问其他内容。DDeiFile中的sheets属性记录了当前文件的页签列表。   一个DDeiFile实例至少包含一个DDeiSheet实例。   本篇最后提供的示例可以在DDei文档直接预览 属性 属性名说明数

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页: