#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
using namespace std;
class String
{
public:
/*explicit*/ String(const char* str= "");
// 复制构造函数
// 不重载复制构造函数,则会调用系统默认的复制构造函数,实现的是浅拷贝
// 浅拷贝:String s("AAAA"); String s2 = s; 等价于 s2.str_ = s.str_;
// 在s2生命周期结果,s2.str_被析构,接着s.str_再次析构,则出现异常
String(const String& other);
// 赋值操作运算符重载
// 赋值操作运算符 String s1("AAAA"); String s2 = s1; 等价于 s2.str_ = s1.str_;
// 调用的是系统默认的赋值操作运算符 实现的是浅拷贝,在s2生命周期结果,s2.str_被析构,接着s1.str_再次析构,则出现异常
String& operator=(const String& other);
String& operator=(const char* str);
bool operator!() const;
// []运算符重载
// 返回值为引用:1、不重新创建字符串对象,2、返回引用可以对该引用进行赋值,进而达到修改String.str_的值
char& operator[](unsigned int index);
// 返回值为const 引用: 当const String s2("abcdef"); s2对象的str_数据是不能被修改
// 申明const: s2是const 对象, 则在该成员函数内均不能被修改
const char& operator[](unsigned int index) const;
// +运算符重载
// 建议使用友元的方式来实现; 不建议使用成员函数实现:原因是成员函数的默认第一个形参是类型自身的引用 如不能实现: String s = s1 + s2;
// 返回值 类型对象: 原因是+运算符是对象与对象相加,对象与字符串相加 从而得到新的对象
// 形参:对象的引用, 不调用构造函数
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 Display() const;
private:
char* AllocAndCpy(const char* str);
char* str_;
};
#endif // _STRING_H_
#pragma warning (disable:4996)
#include "String.h"
#include <string.h>
#include <iostream>
using namespace std;
String::String(const char* str)
{
// 分配内存 赋值
/*int len = strlen(str) + 1;
str_ = new char[len];
memset(str, 0, len);
strcpy(str, str_);*/
str_ = AllocAndCpy(str);
}
// 复制各构造函数:深拷贝
String::String(const String &other)
{
str_ = AllocAndCpy(other.str_);
}
String& String::operator=(const String& other)
{
// 将原来str_空间进行删除
delete[] str_;
str_ = AllocAndCpy(other.str_);
return *this;
}
String& String::operator=(const char* str)
{
delete[] str_;
str_ = AllocAndCpy(str);
return *this;
}
bool String::operator!() const
{
return (strlen(str_) != 0);
}
// 当const 与 non const 的函数体实现一样时:建议non const 调用const
char& String::operator[](unsigned int index)
{
//return str_[index];
// const_cast<> 去除const限定
// static_cast<> 加上const限定
return const_cast<char&>(static_cast<const String&>(*this)[index]);
}
const char& String::operator[](unsigned int index) const
{
return str_[index];
}
String operator+(const String& s1, const String& s2)
{
/*size_t 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 temp(newstr);
delete[] newstr;
return temp;*/
String str = s1;
str += s2;
return str;
}
String& String::operator+=(const String& other)
{
size_t 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;
}
String::~String()
{
delete[] str_;
}
char* String::AllocAndCpy(const char* str)
{
size_t len = strlen(str) + 1;
char* newstr = new char[len];
memset(newstr, 0, len);
// warning C4996: “strcpy”被声明为否决的 取消警告 #pragma warning(disable:code)
strcpy(newstr, str);
return newstr;
}
void String::Display() const
{
cout<<str_<<endl;
}
// char* str.str_ 已经实现了os输出流重载
ostream& operator<<(ostream& os, const String& str)
{
os<<str.str_;
return os;
}
istream& operator>>(istream& is, String& str)
{
char temp[1024];
cin>>temp;
str = temp;
return is;
}
#include "String.h"
#include <iostream>
using namespace std;
int main(void)
{
// [] 运算符重载
String s1("abcdef");
char c = s1[2];
cout<<c<<endl;
s1[2] = 'B';
//s1.Display();
// 当String对象是const 时,使用[]运算符是不能进行赋值的
const String s2("abcdfs");
//s2[2] = 'M'; //error C3892: “s2”: 不能给常量赋值
//s2.Display();
// + 运算符重载
String s3 = "AAAAA";
String s4 = "VVVVV";
String s5 = s4 + s3;
//s5.Display();
String s6 = "XXXX" + s3 + "3131";
//s6.Display();
s3 += s4;
//s3.Display();
cout<<s3<<s4<<endl;
String s7;
cin>>s7;
cout<<s7<<endl;
return 0;
}