#include<iostream>
#include<string.h>
using namespace std;
class String
{
//23種設計模式之代理模式
class charProxy;
public:
String():_pstr(new char[2])
{
cout<<"String()"<<endl;
initRefcount();
}
String(const char *);
String(const String&);
String& operator=(const String&);
~String()
{
cout<<"~String()"<<endl;
decreaseRefcount();
if(0==useCount())
{
delete []_pstr;
}
}
int useCount()
{
return _pstr[strlen(_pstr)+1];
}
charProxy operator[](int index); //區分寫操作,這里要返回一個臨時對象就不能是一個引用了
// char& operator[](int idx)const; //區分讀操作,必須加const關鍵字,不然和前面函數構成重載
private:
char* _pstr;
void initRefcount()
{
_pstr[strlen(_pstr)+1] = 1;
}
void increaseRefcount()
{
++_pstr[strlen(_pstr)+1];
}
void decreaseRefcount()
{
--_pstr[strlen(_pstr)+1];
}
class charProxy
{
public: //這些函數一定要是公有
charProxy(String& str,int index):_str(str),_index(index)
{
cout<<"charProxy(String&,int)"<<endl;
}
char& operator=(char ch); //嵌套類里面,也不能返回對象引用;因為嵌套類對象都是臨時的
operator char()
{ //類型轉換函數,由Charproxy轉向char
cout<<"operator char()"<<endl;
return _str._pstr[_index];
}
private:
String& _str;
int _index;
};
friend ostream& operator<<(ostream&,const String&);
friend istream& operator>>(istream&,String&);
};
#if 0
//operator[]()不能區分讀操作還是寫操作
char & String::operator[](int idx)const //不能區分讀寫操作,廢棄
{
cout<<"operator [](int)const"<<endl;
return _pstr[idx];
}
#endif
String::String(const char* tmp)
{
cout<<"String(const char*)"<<endl;
_pstr = new char[strlen(tmp)+2];
strcpy(_pstr,tmp);
initRefcount(); //引用計數設置為1
}
String::String(const String& lhs)
{
cout<<"String(const String&)"<<endl;
_pstr = lhs._pstr;
increaseRefcount();
}
String& String::operator=(const String& lhs)
{
cout<<"String& operator=(const String&)"<<endl;
decreaseRefcount();
if(0==useCount())
{
delete []_pstr;
}
_pstr = lhs._pstr; // 淺拷貝
increaseRefcount();
return *this;
}
ostream& operator<<(ostream& os,const String& rhs)
{
cout<<"ostream& operator<<(ostream& os,const String&)"<<endl;
os<<rhs._pstr<<endl;
return os;
}
istream& operator>>(istream& is,String& s)
{
cout<<"istream& operator>>(istream&,String&)"<<endl;
is>>s._pstr;
return is;
}
|
String::charProxy String::operator[](int index)
{
cout<<"charProxy operator[](int)"<<endl;
return charProxy(*this,index); //返回臨時嵌套類對象
}
char& String::charProxy::operator=(char ch)
{
cout<<"char& operator=(char)"<<endl;
if(_index>=0&&_index<strlen(_str._pstr))
{
if(1==_str.useCount()) //當對象沒有共享內存時
{
_str._pstr[_index] = ch; //修改
return _str._pstr[_index];
}
else
{
_str.decreaseRefcount(); //有共享內存
char* _strtmp = new char[strlen(_str._pstr)+2];
strcpy(_strtmp,_str._pstr);
_str = _strtmp; //這里調用了構造函數和賦值構造函數,操作完之后調用析構函數
_str[_index] = ch; //這里再次調動[]重載函數,進行修改
_str.initRefcount();
return _str._pstr[_index];
}
}
}
int main()
{
String s1("hello,world");
String s2(s1);
cout<<"讀操作:"<<s1[1]<<endl;
cout<<s1.useCount()<<endl;
cout<<"--------------------------"<<endl;
cout<<"寫操作:"<<endl;
s1[1] = 'm';
cout<<"--------------------------"<<endl;
cout<<s1[1]<<endl;
cout<<s1.useCount()<<endl;
return 0;
}
//String(const char*)
//String(const String&)
//charProxy operator[](int)
//charProxy(String&,int)
//operator char()
//讀操作:e
//2
//--------------------------
//寫操作:
//charProxy operator[](int)
//charProxy(String&,int)
//char& operator=(char)
//String(const char*)
//String& operator=(const String&)
//~String()
//charProxy operator[](int)
//charProxy(String&,int)
//char& operator=(char)
//--------------------------
//charProxy operator[](int)
//charProxy(String&,int)
//operator char()
//m
//1
//~String()
//~String()
|
這里要識別[]操作只能借助嵌套類來底層實現,因為不可能在String類中重寫=運算符;所以當遇到[]操作符的時候就轉化成CharProxy的對象,必須傳引用對其本身操作,在這個類中就可以重寫=運算符來區分讀和寫,因為這里的=我們后面不會再做其他用處只是區分讀寫;所以這里分三步: 重寫[]運算符 先轉換為嵌套類對象 重寫=,區分s[]和是s[]= 改: ![]() 讀: ![]() 讀的時候cout不能輸出CharProxy對象,除非重載;采用類型轉換比較方便,會根據需要自動轉換 |