也许不可能在operator[]内部区分左值还是右值操作,但我们仍然能区别对待读操作和写操作,如果我们将判断读还是写的行为推迟到我们知道operator[]的结果被怎么使用之后的话。我们所需要的是有一个方法将读或写的判断推迟到operator[]返回之后。

proxy类可以让我们得到我们所需要的时机,因为我们可以修改operator[]让它返回一个(代理字符的)proxy对象而不是字符本身。我们可以等着看这个proxy怎么被使用。如果是读它,我们可以断定operator[]的调用是读。如果它被写,我们必须将operator[]的调用处理为写。


文件String.h

 1#ifndef _STRING_H
 2#define _STRING_H
 3
 4#include <ostream>
 5class String
 6{
 7public:
 8    class CharProxy
 9    {
10    public:
11        CharProxy(String& rStr, int nPos):str(rStr), pos(nPos){}
12        CharProxy& operator=(char c)
13        {
14            if( str.value->refCount > 1 )
15            {
16                 --str.value->refCount;
17                 str.value = new StringValue( str.value->data );
18            }

19            str.value->data[pos] = c;
20            return *this;
21        }

22        CharProxy& operator=(const CharProxy& rhs)
23        {
24            if( str.value->refCount > 1 )
25            {
26                 --str.value->refCount;
27                 str.value = new StringValue( rhs.str.value->data );
28            }

29            str.value->data[pos] = rhs.str.value->data[pos];
30            return *this;
31        }

32
33        //convert type of CharProxy to type of char to validate code like:char c = str[0]
34        operator char(){return str.value->data[pos]; }
35
36        //const version of CharProxy to char conversion;
37        operator const char()const{return str.value->data[pos]; }
38
39        //convert type of CharProxy to type of char& to validate code like:char& c = str[0];
40        operator char&()
41        {
42           if( str.value->refCount > 1 )
43           {
44                --str.value->refCount;
45                str.value = new StringValue( str.value->data );
46           }

47           str.value->shareable = false;
48           return str.value->data[pos]; 
49        }

50        //const version of conversion of CharProxy to char&;
51        operator const char&()const{return str.value->data[pos]; }
52        
53        //overload operator ampersand(&) to validate code like:char* p = &str[0];
54        char* operator&()
55        {
56           if( str.value->refCount > 1 )
57           {
58                --str.value->refCount;
59                str.value = new StringValue( str.value->data );
60           }

61           str.value->shareable = false;
62           return &str.value->data[pos]; 
63        }

64        //const version of operator ampersand(&) overloading;
65        const char* operator&()constreturn &str.value->data[pos];}
66
67    private:
68        String& str;
69        int pos;
70    }
;
71
72    String(const char* cszStr = "");
73    String(const String& rhs);
74    String& operator=(const String& rhs);
75    ~String();
76    const char* c_str()const{return value->data;}
77
78public:
79    CharProxy operator[](size_t idx);
80    const CharProxy operator[](size_t idx)const;
81
82public:
83    struct StringValue
84    {
85        size_t refCount;
86        size_t len;
87        bool shareable;
88        char* data;
89    
90        StringValue(const char* cszStr);
91        ~StringValue();
92    }
;
93
94private:
95    StringValue* value;
96}
;
97#endif
98

文件String.cpp

 1#include "String.h"
 2#include <string.h>
 3#include <assert.h>
 4
 5String::String(const char* cszStr)
 6{             
 7    value = new StringValue(cszStr);
 8}

 9
10String::String(const String& rhs)
11{
12    if( rhs.value->shareable )
13    {                
14       value = rhs.value;
15       value->refCount++;
16    }

17    else
18    {
19        value = new StringValue(rhs.value->data);
20    }

21}

22
23String& String::operator=(const String& rhs)
24{
25    if( rhs.value == value )return *this;
26
27    if( rhs.value->shareable )
28    {
29        --value->refCount;
30        if( value->refCount == 0 )delete value;
31        
32        value = rhs.value;
33        ++value->refCount;
34     }

35     else
36     {
37         value = new StringValue(rhs.value->data);
38     }

39    return *this;
40}

41
42String::~String()
43{
44    if--value->refCount == 0 )delete value;
45}

46
47String::CharProxy String::operator[](size_t idx)
48{
49    assert( idx < value->len && idx >= 0);
50    return  String::CharProxy(*this, idx );    
51}

52const String::CharProxy String::operator[](size_t idx)const
53{
54    assert( idx < value->len && idx >= 0);
55    return CharProxy(const_cast<String&>(*this), idx );
56}

57
58String::StringValue::StringValue(const char* cszStr)
59    :refCount(1),shareable(true)
60{
61    len = strlen(cszStr);
62    data = new char[len + 1];
63    if( len == 0 )data[0= '\0';
64    else strcpy(data, cszStr);
65}

66
67String::StringValue::~StringValue()
68{
69    delete[] data;
70    data = 0;
71}

72

测试程序
 1#include <iostream>
 2#include "String.h"
 3
 4using namespace std;
 5
 6std::ostream& operator<< (std::ostream& os, String& str)
 7{
 8    os << str.c_str();
 9    return os;
10}

11int main()
12{
13    String str1 = "hello";
14    String str2(str1);
15
16    cout << "------initial status------" << endl;
17
18    cout << "\tstr1 = " << str1 << endl;
19    cout << "\tstr2 = " << str2 << endl;
20    printf( "\tstr1 address:%p\n", str1.c_str());
21    printf( "\tstr2 address:%p\n", str2.c_str());
22    cout << endl;
23
24
25    cout << "------after reading str1[0]------" << endl;
26    str1[0];
27    cout << "\tstr1 = " << str1 << endl;
28    cout << "\tstr2 = " << str2 << endl;
29    printf( "\tstr1 address:%p\n", str1.c_str());
30    printf( "\tstr2 address:%p\n", str2.c_str());
31    cout << endl;
32
33    cout << "------after writing str1[0]------" << endl;
34    str1[0= 'X';
35    cout << "\tstr1 = " << str1 << endl;
36    cout << "\tstr2 = " << str2 << endl;
37    printf( "\tstr1 address:%p\n", str1.c_str());
38    printf( "\tstr2 address:%p\n", str2.c_str());
39    cout << endl;
40
41    cout << "str1 = " << str1 << endl;
42    char& c = str1[1];
43    c = 'Y';
44    cout << "str1 = " << str1 << endl;
45
46    const char& d = str1[1];
47    cout << "the 2nd character is:" << d << endl;
48
49    char* p = &str1[1];
50    *= 'X';
51    cout << "str1 = " << str1 << endl;
52
53    const char* q = &str1[1];
54    cout << "the 2nd character is:" << *<< endl;
55    
56    system("PAUSE");
57    return EXIT_SUCCESS;
58}

59

posted on 2010-07-13 16:51 mildcat 阅读(178) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理