String原理及实现
string类是由模板类basic_string<class _CharT,class _traits,class _alloc>实例化生成的一个类。basic_tring是由_String_base继承而来的。
typedef basic_string<char> string
#pragma once
#include<iostream>
class String
{
private:
char* data; //字符串内容
size_t length; //字符串长度
public:
String(const char* str = nullptr); //通用构造函数
String(const String& str); //拷贝构造函数
~String(); //析构函数
String operator+(const String &str) const; //重载+
String& operator=(const String &str); //重载=
String& operator+=(const String &str); //重载+=
bool operator==(const String &str) const; //重载==
friend std::istream& operator>>(std::istream &is, String &str);//重载>>
friend std::ostream& operator<<(std::ostream &os, String &str);//重载<<
char& operator[](int n)const; //重载[]
size_t size() const; //获取长度
const char* c_str() const; //获取C字符串
};
#include"String.h"
//通用构造函数
String::String(const char *str)
{
if (!str)
{
length = 0;
data = new char[1]; //一定要用new分配内存,否则就变成了浅拷贝;
*data = '\0';
}
else
{
length = strlen(str); //
data = new char[length + 1];
strcpy(data,str);
}
}
//拷贝构造函数
String::String(const String& str)
{
length = str.size();
data = new char[length + 1]; //一定要用new,否则变成了浅拷贝
strcpy(data,str.c_str());
}
//析构函数
String::~String()
{
delete[]data;
length = 0;
}
//重载+
String String::operator+(const String &str) const
{
String StringNew;
StringNew.length = length + str.size();
StringNew = new char[length + 1];
strcpy(StringNew.data, data);
strcat(StringNew.data, str.data); //字符串拼接函数,即将str内容复制到StringNew内容后面
return StringNew;
}
//重载=
String& String::operator=(const String &str)
{
if (this == &str)
{
return *this;
}
delete []data; //释放内存
length = str.length;
data = new char[length + 1];
strcpy(data,str.c_str());
return *this;
}
//重载+=
String& String::operator+=(const String &str)
{
length += str.size();
char *dataNew = new char[length + 1];
strcpy(dataNew, data);
delete[]data;
strcat(dataNew, str.c_str());
data = dataNew;
return *this;
}
//重载==
bool String::operator==(const String &str) const
{
if (length != str.length)
{
return false;
}
return strcmp(data, str.data) ? false : true;
}
//重载[]
char& String::operator[](int n) const //str[n]表示第n+1个元素
{
if (n >= length)
{
return data[length - 1]; //错误处理
}
else
{
return data[n];
}
}
//获取长度
size_t String::size() const
{
return this->length;
}
//获取C字符串
const char* String::c_str() const
{
return data;
}
//重载>>
std::istream& operator>>(std::istream &is, String &str)
{
char tem[1000];
is >> tem;
str.length = strlen(tem);
str.data = new char[str.length + 1];
strcpy(str.data, tem);
return is;
}
//重载<<
std::ostream& operator<<(std::ostream &os, String &str)
{
os << str.c_str();
return os;
}
关于operator>>和operator<<运算符重载,我们是设计成友元函数(非成员函数),并没有设计成成员函数,原因如下:对于一般的运算符重载都设计为类的成员函数,而>>和<<却不这样设计,因为作为一个成员函数,其左侧操作数必须是隶属同一个类之下的对象,如果设计成员函数,输出为对象>>cout >> endl;(Essential C++)不符合习惯。
一般情况下:
将双目运算符重载为友元函数,这样就可以使用交换律,比较方便
单目运算符一般重载为成员函数,因为直接对类对象本身进行操作
运算符重载函数可以作为成员函数,友元函数,普通函数。
普通函数:一般不用,通过类的公共接口间接访问私有成员。
成员函数:可通过this指针访问本类的成员,可以少写一个参数,但是表达式左边的第一个参数必须是类对象,通过该类对象来调用成员函数。
友元函数:左边一般不是对象。<< >>运算符一般都要申明为友元重载函数