在前面文章中使用过几次String类的例子,现在多重载几个运算符,更加完善一下,并且重载流类运算符。
[]运算符重载
+运算符重载
+=运算符重载
<<运算符重载 >>运算符重载
String.h:
#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
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 index);
const char &operator[](unsigned int index) const;
friend String operator+(const String &s1, const String &s2);
String &operator+=(const String &other);
friend ostream &operator<<(ostream &os, const String &str);
friend istream &operator>>(istream &is, String &str);
~String(void);
void Display() const;
int Length() const;
bool IsEmpty() const;
private:
String &Assign(const char *str);
char *AllocAndCpy(const char *str);
char *str_;
};
#endif // _STRING_H_
String.cpp:
#pragma warning(disable:4996)
#include "String.h"
#include <string.h>
//#include <iostream>
//using namespace std;
String::String(const char *str)
{
str_ = AllocAndCpy(str);
}
String::String(const String &other)
{
str_ = AllocAndCpy(other.str_);
}
String &String::operator=(const String &other)
{
if (this == &other)
return *this;
return Assign(other.str_);
}
String &String::operator=(const char *str)
{
return Assign(str);
}
String &String::Assign(const char *str)
{
delete[] str_;
str_ = AllocAndCpy(str);
return *this;
}
bool String::operator!() const
{
return strlen(str_) != 0;
}
char &String::operator[](unsigned int index)
{
//return str_[index];
//non const 版本调用 const版本
return const_cast<char &>(static_cast<const String &>(*this)[index]);
}
const char &String::operator[](unsigned int index) const
{
return str_[index];
}
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;
}
void String::Display() const
{
cout << str_ << endl;
}
int String::Length() const
{
return strlen(str_);
}
bool String::IsEmpty() const
{
return Length() == 0;
}
String operator+(const String &s1, const String &s2)
{
//int len = strlen(s1.str_) + strlen(s2.str_) + 1;
//char* newstr = new char[len];
//memset(newstr, 0, len);
//strcpy(newstr, s1.str_);
//strcat(newstr, s2.str_);
//
//String tmp(newstr);
//delete newstr;
String str = s1;
str += s2;
return str;
}
String &String::operator+=(const String &other)
{
int len = strlen(str_) + strlen(other.str_) + 1;
char *newstr = new char[len];
memset(newstr, 0, len);
strcpy(newstr, str_);
strcat(newstr, other.str_);
delete[] str_;
str_ = newstr;
return *this;
}
ostream &operator<<(ostream &os, const String &str)
{
os << str.str_;
return os;
}
istream &operator>>(istream &is, String &str)
{
char tmp[1024];
cin >> tmp;
str = tmp;
return is;
}
main.cpp:
#include "String.h"
#include <iostream>
using namespace std;
int main(void)
{
String s1("abcdefg");
char ch = s1[2];
cout << ch << endl;
s1[2] = 'A';
s1.Display();
const String s2("xyzabc");
ch = s2[2];
//s2[2] = 'M'; Error
s2.Display();
String s3 = "xxx";
String s4 = "yyy";
String s5 = s3 + s4;
s5.Display();
String s6 = "aaa" + s3 + "sdfadfa" + "xxxx";
s6.Display();
s3 += s4;
s3.Display();
cout << s3 << endl;
String s7;
cin >> s7;
cout << s7 << endl;
if (!s7.IsEmpty())
cout<<s7.Length()<<endl;
return 0;
}
需要注意的是,不能将String类的构造函数声明为explicit,否则 String s3 = "xxx"; 编译出错;operator[] 的non const 版本调用了const 版本的实现,其中使用了static_cast和 const_cast 两种类型转换操作符,可以参考这里;operator+ 调用了operator+= 的实现;只能将流类运算符重载为友元函数,因为第一个参数是流类引用,不是String 类。
通过实现这样一个字符串类,我们可以熟悉基本的内存管理与拷贝控制。
参考:
C++ primer 第四版 Effective C++ 3rd C++编程规范