在实现自己的string类之前,我们先来了解一下标准库的string类型。
string类型支持长度可变的字符串,C++标准库将负责管理与存储字符相关的内存,以及提供各种有用的操作。标准库string类型的目的就是满足对字符串的一般应用。要使用string类型的对象,必须加上头文件:#include<string>
#include<iostream>
#include<string>
using namespace std;
//string类
class CString
{
public:
//构造
CString(char *p = NULL)
{
if(p != NULL)//传进来的字符串判空
{
_pstr = new char[strlen(p)+1];
strcpy(_pstr,p);
}
else
{
_pstr = new char[1];//若为空则赋予其一个char类型字节的长度
*_pstr = '\0';
}
}
//析构
~CString()
{
delete []_pstr;
_pstr = NULL;
}
//拷贝构造
CString(const CString &src)
{
_pstr = new char[strlen(src._pstr)+1];
strcpy(_pstr,src._pstr);
}
//赋值构造
CString &operator=(const CString &src)
{
if(&src == this)
{
return *this;
}
delete []_pstr;
_pstr = new char[strlen(src._pstr)+1];
strcpy(_pstr,src._pstr);
return *this;
}
//如果两个string对象长度不同,且短的string对象与长的string对象的前面部分相匹配,则短的string对象小于
//两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止。
//重载>
bool operator>(const CString &src)const
{
return strcmp(_pstr,src._pstr) > 0;
}
//重载<
bool operator<(const CString &src)const
{
return strcmp(_pstr,src._pstr) < 0;
}
//重载==
bool operator==(const CString &src)const
{
return strcmp(_pstr,src._pstr) == 0;
}
//得到字符串长度
int length()const
{
return strlen(_pstr);
}
//重载[]
char operator[](int index)const
{
if(index < 0 || index >strlen((this->_pstr)))
throw "下标越界!";
return _pstr[index];
}
//实现c_str()
const char* c_str()const
{
return _pstr;
}
//定义CString的迭代器类型
class iterator
{
public:
//构造
iterator(char *p) :it_str(p){}
//重载迭代器的!=
bool operator!=(const iterator &it)
{
return it_str != it.it_str;
}
//重载迭代器前置++
void operator++()
{
it_str++;
}
//重置迭代器解引用*
char& operator*()
{
return *it_str;
}
private:
char *it_str;//迭代器指针
};
//实现迭代器begin()函数
iterator begin()//返回容器0号元素的迭代器
{
return iterator(_pstr);
}
//实现迭代器end()函数
iterator end()//返回容器最后一个元素后继位置的迭代器
{
return iterator(_pstr + length());
}
private:
char *_pstr;
friend ostream &operator<<(ostream &out, const CString &str);//声明<<重载函数为友元函数
friend CString operator+(const CString &lhs, const CString &rhs);//声明+重载函数为友元函数
};
//重载+
CString operator+(const CString &lhs, const CString &rhs)
{
char *p = new char[strlen(lhs._pstr)+strlen(rhs._pstr)+1];//为连接好的字符串开辟空间
strcpy(p,lhs._pstr);//拷贝lhs的字符串
strcat(p,rhs._pstr);//拷贝rhs的字符串
CString tmp(p);//用p构造临时对象
delete []p;//析构p
return tmp;//返回连接后的字符串
}
//重载<<
ostream &operator<<(ostream &out, const CString &str)
{
out << str._pstr ;
return out;
}
实现过程中大部分知识来自于字符串基础知识,除此之外,还将一部分运算符进行了重载!那么运算符重载是什么?
C++ 运算符重载的目的:让对象的运算表现的和内置类型一样。什么是内置类型?内置类型就是int,char等计算机内部本身就存在的类型。在运算符重载函数中有一部分实现在类内,一部分实现在类外。编译器优先去类的成员方法里面查找运算符重载函数(对象在左边),如果没有,然后再到全局找合适的运算符重载函数(对象在右边)
可重载操作符(如图)
不可重载操作符:①:: ②.* ③. ④:?
重载操作符函数的定义:
重载操作符是具有特殊名称的函数:保留字operator后加需重载的操作符。重载操作符函数具有返回类型和形参列表。
这里要提到一个特殊的符号"++",因为前置++和后置++在形式上符号是无法区分的。所以规定在前置++的重载函数的形参列表中多了一个只有int类型名无参数名的列表。
CComplex operator++()//后置++
CComplex operator++(int) //前置++
还有另外一个运算符的重载"()"
有operator()运算符重载的对象,一般使用在泛型算法当中,改变泛型算法的行为,使其能够内联,节省函数的调用开销