技术(6)—代理类

Item 30 代理类:“用来代表其他对象”的对象。

(1)阻止只有一个参数的类执行隐式类型转换的方法。

template <typename T>
class Array
{
public:
	class ArraySize
	{
	public:
		ArraySize(int numElements):theSize(numElements) {}
		int size() const {return theSize;}
	private:
		int theSize;
	};

	Array(ArraySize size);
};

其中ArraySize就是数组大小的一个代理类。

Array<int> a(10);

Array<int> b(10);在构造的过程中,编译器将int通过隐式类型转换转为ArraySize的一个临时对象,然后调用Array<int>的构造函数。

如果出现这样的代码:

if(a==b[i])  //a的类型为array<int>,而b[i]的类型为int,则若将int转为一个临时的ArraySize,然后根据ArraySize再构造一个临时的array<int>,这样的行为编译器不允许,不会连续执行两次以上的隐式类型转换。若不采用代理类,则直接根据int就可以构造一个Array<int>可以编译通过。

(2)区分operator[]的读写操作。

采用带引用计数、使用代理类的String做例子:

RCObject同上篇。

RCPtr如下:

template <typename T>
class RCPtr
{
public:
	RCPtr(T* realPtr=0);
	RCPtr(const RCPtr& rhs);
	~RCPtr(void);

	RCPtr& operator=(const RCPtr& rhs);
	T* operator->() const;
	T& operator*() const;
private:
	T* pointee;
	void init();
};

template <typename T>
void RCPtr<T>::init()
{
	if(pointee==nullptr) return;

	if(pointee->isShareable()==false)
	{
		pointee=new T(*pointee);
	}

	pointee->addReference();
}

template <typename T>
RCPtr<T>::RCPtr(T* realPtr):pointee(realPtr)
{
	init();
}

template <typename T>
RCPtr<T>::RCPtr(const RCPtr& rhs):pointee(rhs.pointee)
{
	init();
}

template <typename T>
RCPtr<T>::~RCPtr()
{
	if(pointee)
		pointee->removeReference();
}

template <typename T>
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs)
{
	if(pointee!=rhs.pointee)
	{
		if(pointee)
			pointee->removeReference();
		pointee=rhs.pointee;
		init(); 
	}

	return *this;
}

template <typename T>
T& RCPtr<T>::operator*() const
{
	return *pointee;
}

template <typename T>
T* RCPtr<T>::operator->() const
{
	return pointee;
}

String头文件:

#include <iostream>
using namespace std;

#include "RCObject.h"
#include "RCPtr.h"

class String
{
public:
	class CharProxy
	{
	public:
		CharProxy(String& str,int index):theString(&str),charIndex(index) {}
		CharProxy& operator=(const CharProxy& rhs);
		CharProxy& operator=(char c);

		char* operator&();
		const char* operator&() const;

		operator char() const;
	private:
		void assignment(char c);
		String* theString;
		int charIndex;
	};

	friend class CharProxy;

	String(const char* value="");
	const CharProxy operator[](int index) const;
	CharProxy operator[](int index);
private:
	struct StringValue:public RCObject
	{
		char* data;
		StringValue(const char* initValue);
		StringValue(const StringValue& rhs);
		void init(const char* initValue);
		~StringValue();
	};
	RCPtr<StringValue> value;
	friend ostream& operator<<(ostream& os,const String& str)
	{
		os<<str.value->data;
		return os;
	}
};


String实现文件:

#include "String.h"

String::CharProxy::operator char() const
{
	return theString->value->data[charIndex];
}

void String::CharProxy::assignment(char c)
{
	if(theString->value->isShared())
		theString->value=new StringValue(theString->value->data);
	theString->value->data[charIndex]=c;
}

String::CharProxy& String::CharProxy::operator=(const String::CharProxy& rhs)
{
	assignment(rhs.theString->value->data[charIndex]);
	return *this;
}

String::CharProxy& String::CharProxy::operator=(char c)
{
	assignment(c);
	return *this;
}

const char* String::CharProxy::operator&() const
{
	return &(theString->value->data[charIndex]);
}

char* String::CharProxy::operator&()
{
	if(theString->value->isShared())
		theString->value=new StringValue(theString->value->data);

	theString->value->markUnshareable();
	return &(theString->value->data[charIndex]);
}

void String::StringValue::init(const char* initValue)
{
	data=new char[strlen(initValue)+1];
	strcpy_s(data,strlen(initValue)+1,initValue);
}

String::StringValue::StringValue(const char* initValue)
{
	init(initValue);
}

String::StringValue::StringValue(const StringValue& rhs)
{
	init(rhs.data);
}

String::StringValue::~StringValue()
{
	delete[] data;
}

String::String(const char* initValue):value(new StringValue(initValue))
{
	
}

const String::CharProxy String::operator[](int index) const
{
	return CharProxy(const_cast<String&>(*this),index);
}

String::CharProxy String::operator[](int index)
{
	return CharProxy(*this,index);
}

例子分析:

int _tmain(int argc, _TCHAR* argv[])
{
	String str1="Hello";
	String str2="How many!!";

	cout<<str1[2]<<endl;
	str2[5]='y';
	return 0;
}

在cout<<str1[2]<<endl;这句中,首先通过CharProxy operator[](int index);返回一个CharPorxy对象,然后调用operator char() const;转为char型,然后输出。

在str2[5]='y';这句中,首先通过CharProxy operator[](int index);返回一个CharProxy对象,然后调用CharProxy& operator=(char c);来完成操作。

因此这样就通过代理类的两个成员分清楚了是读操作,还是写操作。


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值