如何在C++中创建具有基本功能的自定义String类
C++中的字符串是由标准库提供的string类来管理的,但是有时候我们需要自定义一个string类来满足我们的需求。本文将分享如何在C++中创建具有基本功能的自定义String类。
步骤1:创建String类的头文件
我们要先创建一个头文件String.h来存放String类的定义和声明。下面是一个基本的String类的定义:
#ifndef STRING_H
#define STRING_H
//头文件
#include <iostream>
#include <cstring>
class String
{
public:
//构造函数
String ();
String (const char*);
String (const String&);
//析构函数
~String ();
//运算符重载
String& operator = (const char*);
String& operator = (const String&);
friend String operator + (const String&, const String&);
friend bool operator ==(const String&, const String&);
friend bool operator !=(const String&, const String&);
friend bool operator <(const String&, const String&);
friend bool operator >(const String&, const String&);
friend bool operator <=(const String&, const String&);
friend bool operator >=(const String&, const String&);
char& operator [](int);
friend std::istream& operator >> (std::istream&, String&);
friend std::ostream& operator << (std::ostream&, const String&);
//函数
int length ();
String substr(int, int);
void clear();
protected:
char* m_data;
private:
};
#endif // STRING_H
上面的定义中包含了String类的构造和析构函数、运算符重载,以及一些常用的函数的声明。我们还定义了一个char类型的指针m_data,它是String类的数据成员,存储String类所表示的字符串。
步骤2:实现String类的构造函数和析构函数
下面是String类的构造函数和析构函数的实现代码:
String::String()
{
m_data = new char[1];
*m_data = '\0';
}
String::String(const char* str)
{
if (str)
{
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
}
String::String(const String& other)
{
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
}
String::~String()
{
delete[] m_data;
}
在构造函数中,我们使用了new运算符来动态地分配内存,可以避免在编译时给字符串指定固定长度的麻烦。这里需要注意的是,在分配内存时需要在字符串的长度上加1来保证字符串结尾有一个空字符。
在析构函数中,我们使用了delete[]运算符来释放动态分配的内存,并将指向内存空间的指针m_data设为NULL。
步骤3:实现String类的运算符重载
下面是String类的一些常用运算符的实现代码:
String& String::operator=(const char* str)
{
if (m_data == str)
{
return *this;
}
if (m_data != NULL)
{
delete[] m_data;
}
if (str)
{
m_data = new char[strlen(str) + 1];
strcpy(m_data, str);
}
else
{
m_data = new char[1];
*m_data = '\0';
}
return *this;
}
String& String::operator=(const String& other)
{
if (m_data == other.m_data)
{
return *this;
}
if (m_data != NULL)
{
delete[] m_data;
}
m_data = new char[strlen(other.m_data) + 1];
strcpy(m_data, other.m_data);
return *this;
}
char& String::operator [](int index)
{
return *(m_data + index);
}
上面的代码实现了赋值运算符、下标运算符的重载。我们需要考虑到各种情况,比如处理空指针、避免产生内存泄漏等。
另外,为了能够通过串联运算符“+”将两个字符串拼接起来,我们需要重载“+”运算符。下面是实现代码:
String operator+(const String& lhs, const String& rhs)
{
String result;
result.m_data = new char[strlen(lhs.m_data) + strlen(rhs.m_data) + 1];
strcpy(result.m_data, lhs.m_data);
strcat(result.m_data, rhs.m_data);
return result;
}
bool operator==(const String& lhs, const String& rhs)
{
return strcmp(lhs.m_data, rhs.m_data) == 0;
}
bool operator!=(const String& lhs, const String& rhs)
{
return !(lhs == rhs);
}
bool operator<(const String& lhs, const String& rhs)
{
return strcmp(lhs.m_data, rhs.m_data) < 0;
}
bool operator>(const String& lhs, const String& rhs)
{
return strcmp(lhs.m_data, rhs.m_data) > 0;
}
bool operator<=(const String& lhs, const String& rhs)
{
return strcmp(lhs.m_data, rhs.m_data) <= 0;
}
bool operator>=(const String& lhs, const String& rhs)
{
return strcmp(lhs.m_data, rhs.m_data) >= 0;
}
std::istream& operator>>(std::istream& is, String& str)
{
char temp[1024];
is >> temp;
str = temp;
return is;
}
std::ostream& operator<<(std::ostream& os, const String& str)
{
os << str.m_data;
return os;
}
步骤4:实现String类的一些常用函数
下面是String类的一些常用函数的实现代码:
int String::length()
{
return strlen(m_data);
}
String String::substr(int start, int len)
{
if (start < 0)
{
start = 0;
}
if (len < 0)
{
len = 0;
}
if (start + len > strlen(m_data))
{
len = strlen(m_data) - start;
}
char* temp = new char[len + 1];
strncpy(temp, m_data + start, len);
temp[len] = '\0';
String result(temp);
delete[] temp;
return result;
}
void String::clear()
{
if(m_data != NULL)
{
delete[] m_data;
m_data = new char[1];
*m_data = '\0';
}
}
我们实现了返回字符串长度的函数length(),返回从起始位置start开始的长度为len的子串的函数substr(),以及清空字符串内容的函数clear()。
步骤5:测试自定义String类
现在可以愉快的进行测试了。下面是一些测试代码:
# include "String.h"
# include <iostream>
using namespace std;
int main()
{
String str1("hello");
String str2 = "world";
String str3(str2);
//测试构造函数
cout << "str1:" << str1 << " str2:" << str2 << endl;
//测试"="运算符
str2 = str1;
cout << "str1:" << str1 << " str2:" << str2 << endl;
//测试"+"运算符
String str4 = str1 + " " + str2 + "!";
cout << "str4:" << str4 << endl;
//测试下标运算符和长度函数
for (int i = 0; i < str1.length(); ++i)
{
cout << str1[i] << " ";
}
cout << endl;
//测试子串函数
String str5 = str4.substr(6, 5);
cout << "str5:" << str5 << endl;
//测试比较运算符
if (str1 == str2)
{
cout << "str1 equal to str2" << endl;
}
if (str1 != str2)
{
cout << "str1 not equal to str2" << endl;
}
if (str1 < str2)
{
cout << "str1 less than str2" << endl;
}
if (str1 > str2)
{
cout << "str1 greater than str2" << endl;
}
if (str1 <= str2)
{
cout << "str1 less than or equal to str2" << endl;
}
if (str1 >= str2)
{
cout << "str1 greater than or equal to str2" << endl;
}
//测试输入输出运算符
String str6;
cout << "Please enter a string:";
cin >> str6;
cout << "str6:" << str6 << endl;
//测试clear函数
str6.clear();
cout << "after clear, str6:" << str6 << endl;
return 0;
}
结论
通过上述步骤的实现,我们已经成功地创建了一个具有基本功能的自定义String类。String类的定义和实现可以方便地在程序中使用,也可以帮助学习者更深入地理解C++中的类和对象的概念。