operator[],識別讀操作和寫操作



#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對象,除非重載;采用類型轉換比較方便,會根據需要自動轉換



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM