Proxy class与左值右值运用
我们修改operator[],令它返回字符串中的字符的proxy,而不返回字符本身。等待最终结果到底是如何运用的。
//1.指定它代表哪一个字符串中的哪一个字符
//2.赋值代表则为那个字符串的左值运用
//3.以其他方式使用之,调用operator[]函数则为右值运用
之后再考虑当有operator=时运用左值运用,其余时候为右值运用。
详细见class CharProxy,它就是返回的proxy class,针对于proxy重载所需要的左右值运用。
template<class T>class RCPtr//智能指针
{
public:
RCPtr(T* realPtr)
:pointee(realPtr) {
init();
}
RCPtr(const RCPtr& rhs)
:pointee(rhs.pointee) {
init();
}//拷贝构造函数
~RCPtr()
{
if (pointee)pointee->removeReference();
}
RCPtr& operator=(const RCPtr& rhs)
{
if (pointee != rhs.pointee)
{
if (pointee)
pointee->removeReference();
pointee = rhs.pointee;
init();
}
return *this;
}//赋值构造函数
T* operator->() const
{
return pointee;
}//指向函数
T& operator*() const
{
return *pointee;
}//解引用构造函数
private:
T *pointee;//dump指针
void init();
};
template<class T>void RCPtr<T>::init()
{
if (pointee == 0)return;//如果dumb pointer是null,那么smart pointer也是。
if (pointee->isShareable() == false)
{
pointee = new T(*pointee); //如果其值不可共享,就复制一份
//调用的是String::StringValue的拷贝构造函数
}
pointee->addReference();
}
class RCObject
{
public:
void addReference()
{
++refCount;
}
void removeReference()
{
if (--refCount == 0)
delete this;
}
void markUnshareable()
{
shareable = false;
}
bool isShareable() const
{
return shareable;
}
bool isShared() const
{
return refCount>1;
}
protected:
RCObject()
:refCount(0), shareable(true) {};
RCObject(const RCObject& rhs)
:refCount(0), shareable(true) {};
RCObject& operator=(const RCObject& rhs)
{
return *this;
}
virtual ~RCObject() {};
private:
int refCount;
bool shareable;
};
class String
{
public:
String(const char*value = "");
//1.指定它代表哪一个字符串中的哪一个字符
//2.赋值代表则为那个字符串的左值运用
//3.以其他方式使用之,调用operator[]函数则为右值运用
class CharProxy
{
public:
CharProxy(String& str, int index)
:theString(str),charIndex(index){}
CharProxy& operator=(const CharProxy& rhs)//左值运用
{
if (theString.value->isShared())
{
theString.value = new StringValue(theString.value->data);
}
theString.value->data[charIndex] = rhs.theString.value->data[charIndex];
return *this;
}
CharProxy& operator=(char c)
{
if (theString.value->isShared())
{
theString.value = new StringValue(theString.value->data);
}
theString.value->data[charIndex] = c;
return *this;
}
operator char()const//右值运用
{
return theString.value->data[charIndex];
}
private:
String& theString;
int charIndex;
};
const CharProxy operator[](int index)const
{
return CharProxy(const_cast<String&>(*this), index);//去掉const
}
CharProxy operator[](int index)
{
return CharProxy(*this, index);
}
//只确定是哪个字符串中的哪个字符
friend class CharProxy;
private:
struct StringValue :public RCObject
{
char *data;
StringValue(const char *initValue)
{
init(initValue);
}
StringValue(const StringValue& rhs)
{
init(rhs.data);
}
void init(const char *initValue)
{
data = new char[strlen(initValue) + 1];
strcpy(data, initValue);
}
~StringValue()
{
delete[]data;
}
};
RCPtr<StringValue> value;
};
缺陷:
对proxy取址所获得的指针型与对真实对象取址所获的指针型别不同。
CharProxy转换为char是错误的。
注意:编译器在【将调用端自变量转换为对应的被调用端函数参数】过程中,运用【用户定制转换函数】的次数只限于一次。