一、String类的实现
我们继续实现以下功能:
[]运算符重载
+运算符重载
+=运算符重载
<<运算符重载
>>运算符重载
例子代码:
#include <iostream>
#include <string>
using namespace std;
class String
{
public:
String(const char* str="");
String(const String& other);
String& operator=(const String& other);
String& operator=(const char* str);
bool operator!() const;
char& operator[](unsigned int i);
const char& operator[](unsigned int i) const;
friend String operator+(const String& a,const String &b);
String& operator+=(const String &a);
friend ostream& operator<<(ostream& os, const String& a);
friend istream& operator>>(istream& is, String& a);
~String(void);
void Display() const;
private:
String& Assign(const char* str);
char* AllocAndCpy(const char* str);
char* str_;
};
String::String(const char* str)
{
str_ = AllocAndCpy(str);
}
String::String(const String& other)
{
str_ = AllocAndCpy(other.str_);
}
String& String::Assign(const char* str)
{
delete[] str_;
str_ = AllocAndCpy(str);
return *this;
}
String& String::operator=(const String& other)//深拷贝
{
if (this == &other)
return *this;
return Assign(other.str_);
}
String& String::operator=(const char* str) //深拷贝
{
return Assign(str);
}
bool String::operator!() const
{
return strlen(str_) != 0;//字符串不为空即为true
}
char& String::operator[](unsigned int i)
{
//return str_[i];
//实现时尽量以非const版本函数调用const版本对象函数
return const_cast<char&>(static_cast<const String&>(*this)[i]);
}
const char& String:: operator[](unsigned int i) const
{
return str_[i];
}
String operator+(const String& a,const String &b)
{
String tmp = a;;
tmp += b;
return tmp;
}
String::~String()
{
delete[] str_;
}
char* String::AllocAndCpy(const char* str)
{
int len = strlen(str) + 1;
char* newstr = new char[len];
memset(newstr, 0, len);
strcpy(newstr, str);
return newstr;
}
String& String::operator+=(const String &other)
{
int len = strlen(other.str_) + strlen(str_) + 1;
char *newstr = new char[len+1];
memset(newstr, 0, len);
strcpy(newstr,str_);
strcat(newstr,other.str_);
delete[] str_;
str_ = newstr;
return *this;
}
ostream& operator<<(ostream& os, const String& a)
{
os<<a.str_;
return os;
}
istream& operator>>(istream& is, String& str)
{
char tmp[1024];
is>>tmp;
str = tmp;
return is;
}
void String::Display() const
{
cout<<str_<<endl;
}
int main(void)
{
String s("abcdef");
char t = s[3];
cout<<t<<endl;
s[3] = '5';
s.Display();
const String s1("12345");
//const对象调用const类型函数,不能改变对象状态
//s1[2] = '4';
s1.Display();
String s2 = s1 + s;
s2.Display();
//字符串"123"会转换为类对象
s2 = "123" + s1;
s2 = "123" + s1 + s;
s2.Display();
s += "1111";
//<<运算符重载
cout<<s<<endl;
//>>运算符重载
cin>>s;
cout<<s<<endl;
return 0;
}
注意:流运算符的重载只能使用友元函数进行重载,为什么呢?我们看下流运算符重载的形式:
friend
istream
& operator>>(
istream
&,
类类型
&);
friend
ostream
& operator<<(
ostream
&, const
类类型
&);
可以看出,流运算符重载的第一个参数都是流对象,而成员函数重载的第一个参数都是对象自身(this),所以流运算符的重载只能使用友元函数。
另外,在编码的过程中,尽量把那些重复的操作提取出来作为一个函数,在编写一个新的模块时,尽量复用现有模块,提高代码的可读性和复用性。