1、头文件
StringTest.h
#ifndef STRINGTEST_H
#define STRINGTEST_H
#include <iostream>
#include <cstring>
class StringTest
{
private:
char* data_;
size_t size_;
public:
StringTest(); // 空构造
StringTest(const char* str); // 普通构造
StringTest(const StringTest& other); // 拷贝构造
~StringTest(); // 析构函数
char& operator[](size_t index); // 重载[]运算符
bool operator==(const StringTest& other); // 重载==
StringTest operator+(const StringTest& other); // 重载+
const char* c_str() const; // 转换成c风格的字符串
size_t length(); // 获得字符串长度
friend std::ostream& operator<<(std::ostream& out,const StringTest& str); //友元的方式 重载<<
friend std::istream& operator>>(std::istream& in,StringTest& str); //友元的方式 重载>>
private:
void __init(const char* str); // 分配内存
void __clean(); // 清除内存
};
#endif
(1)这里使用char*字符串+size_的方式实现的;
(2)首先有空构造、普通构造、拷贝构造、析构函数(特别注意参数);
(3)接着是重载[]、==、+、<<、>>操作符(特别注意参数、返回值类型);
(4)为了减少代码的冗余,这里提供了_init(const char* str)和_clean()函数,用户分配内存和清除内存,主要用在构造函数和析构函数中。
2、实现
StringTest.cpp
#include "StringTest.h"
// 分配内存
void StringTest::__init(const char* str)
{
//传入空字符串
if(str == nullptr)
{
this->data_ = nullptr;
this->size_ = 0;
}
else
{
this->size_ = std::strlen(str);
this->data_ = new char[this->size_ + 1];
strncpy(this->data_, str, this->size_ + 1);
}
}
// 清除内存
void StringTest::__clean()
{
if (this->data_ != nullptr)
{
delete[] this->data_;
}
this->size_ = 0;
}
//空构造
StringTest::StringTest():data_(nullptr),size_(0){}
//普通构造
StringTest::StringTest(const char* str)
{
__init(str);
}
//拷贝构造
StringTest::StringTest(const StringTest& other)
{
std::cout<<"copy construct"<<std::endl;
__init(other.data_);
}
//析构函数
StringTest::~StringTest()
{
__clean();
}
//重载[]运算符
char& StringTest::operator[](size_t index)
{
//越界抛异常
if(index >= this->size_)
{
throw"index out of range";
}
return this->data_[index];
}
//重载==运算符
bool StringTest::operator==(const StringTest& other)
{
if(other.size_ != this->size_)
{
return false;
}
return 0 == std::strcmp(this->data_,other.data_);
}
//重载+运算符
StringTest StringTest::operator+(const StringTest& other)
{
if (other.size_ == 0)
{
return *this;
}
else if (this->size_ == 0)
{
return other;
}
//存储加了之后的数据
StringTest s;
s.size_ = this->size_ + other.size_;
s.data_ = new char[s.size_ + 1];
strncpy(s.data_, this->data_, this->size_);
strncpy(s.data_ + this->size_, other.data_, other.size_);
s.data_[s.size_] = '\0';
return s;
}
//转换成c风格的字符串
const char* StringTest::c_str() const
{
return this->data_;
}
//获得字符串长度
size_t StringTest::length()
{
return this->size_;
}
//重载<<
std::ostream& operator<<(std::ostream& out,const StringTest& str)
{
if(str.data_ == nullptr)
{
out<<"";
}
else
{
out<<str.data_;
}
return out;
}
//重载>>
std::istream& operator>>(std::istream& in,StringTest& str)
{
std::cout<<"Please input StringTest size:";
in>>str.size_;
str.data_ = new char[str.size_ + 1];
std::cout<<"Please input StringTest data";
in>>str.data_;
int len = std::strlen(str.data_);
if(len > str.size_)
{
std::cout<<"error! data len > size"<<std::endl;
exit(1);
}
return in;
}
(1)首先是实现__init(const char* str)函数,即根据传入str指针分配内存;
(2)清除内存;
(3)空构造:data_ 指向空,size_等于0;
(4)普通构造:调用__init(const char* str)函数;
(5)拷贝构造:调用__init(const char* str)函数;
(6)析构函数:调用__clean()函数;
(7)重载[];
(8)重载==运算符;
(9)重载+运算符;
(10)重载<<;
(11)重载>>;
(12)这里需要特别注意的就是strncpy函数的使用。
函数原型char*strncpy(char*dest,char*src,size_t n);把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
主要代码段
this->size_ = std::strlen(str);
this->data_ = new char[this->size_ + 1];
strncpy(this->data_, str, this->size_ + 1);
先求出str的长度(不含'\0');
再申请this->size_ + 1的内存空间;
最后把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。(包含'\0');
(13)还需要注意重载+运算符
StringTest StringTest::operator+(const StringTest& other)
{
if (other.size_ == 0)
{
return *this;
}
else if (this->size_ == 0)
{
return other;
}
//存储加了之后的数据
StringTest s;
s.size_ = this->size_ + other.size_;
s.data_ = new char[s.size_ + 1];
strncpy(s.data_, this->data_, this->size_);
strncpy(s.data_ + this->size_, other.data_, other.size_);
s.data_[s.size_] = '\0';
return s;
}
用s存储相加之后的数据,再申请空间,最后逐一拷贝进去。
3、test
test.cpp
#include "StringTest.h"
int main(int argc,char* argv[])
{
std::cout << "copy constructor test" << std::endl;
StringTest x("xxx");
// 拷贝构造
StringTest cop = x;
std::cout << "copy assignment test" << std::endl;
// copy assignment
x = cop;
std::cout << "operator<< test" << std::endl;
StringTest c = StringTest("hello");
std::cout << c << std::endl;
std::cout << "operator>> test" << std::endl;
StringTest in;
std::cin >> in;
std::cout << in << std::endl;
std::cout << "operator == test" << std::endl;
StringTest aa = "hello";
StringTest bb = "hello";
StringTest cc = "hello1";
std::cout << (aa == bb) << "," << (aa == cc) << std::endl;
std::cout << "operator+ test" << std::endl;
StringTest ad;
StringTest bd("lucy");
StringTest cd = ad + bd;
std::cout << cd << std::endl;
std::cout << "c_str() test" << std::endl;
std::cout << cd.c_str() << std::endl;
std::cout << "legth() test" << std::endl;
std::cout << cd.length() << std::endl;
system("pause");
return 0;
}