目录
一、前言
二、设计需求
三、设计思想
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;
}
// 获取len
unsigned short getLen() const
{
return len;
}
// 获取 m_str
char* 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);
}
// 获取len
unsigned short getLen() const
{
return len;
}
// 获取 m_str
char* 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的完整版,还请各位彦祖们多多支持!!!