More Effective C++之30

条款30: Proxy Classes(替身类/代理类)

       相信么?C++缺乏对多维数组的有力支持.当我申明一个多维数组char strArray[10][10][10],仅仅意味着在栈上分配了1000Bytes的内存.对C++来说,可以理解这是一维数组.那么下面这就不好玩了.
int i = 10;

       char strArray = new char[i][i][i];

不要希望C++支持这样的语法,对,它不能.所以对二维数组,我们要付出我们自己的努力.用Proxy实现二维数组,正是体现Proxy的优势。
 
区分operator[]的读写动作
class RCObject
{
public :
       RCObject (): refCount (0), shareable ( true ){}
       RCObject ( const RCObject &): refCount (0), shareable ( true ){}
       RCObject & operator =( const RCObject & rhs ){ return * this ;}
       virtual ~ RCObject ()=0;
       void AddReference (){++ refCount ;}

       voidRemoveReference(){if (--refCount == 0) deletethis;}

       void markUnshareable (){ shareable = false ;}
       bool isShareable () const { return shareable ;}
       bool isShared () const { return refCount > 1;}
private :
       int refCount ;
       bool shareable ;
};
RCObject ::~ RCObject (){}
 
template < class T >
class RCPtr
{
public :
       RCPtr ( T * realPtr = 0): 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 ;
       void init ()
       {
              if ( pointee == 0)
                     return ;
              if ( pointee -> isShareable () == false )
                     pointee = new T (* pointee );
              pointee -> AddReference ();
       }
};
 
class String
{
public :
       String ( const char * value = "" ): value ( new StringValue ( value )){}
       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 [ rhs . 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 ];
              }
       protected :
       private :
              String & theString ;
              int charIndex ;
       };
       const CharProxy operator []( int index ) const
       {
              return CharProxy ( const_cast < String &>(* this ), index );
       }
       CharProxy operator []( int index )
       {
              return CharProxy (* this , index );
       }
       friend class CharProxy ;
protected :
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在这里做一个判定的延迟,由于应用了Proxy(),这里有了对读写的判断标准。对于所有的operator[]都记录了index,返回一个CharProxy,那么下面就可以做文章了,如果只是需要读,也就是说返回一个char,那么使用char()的隐式转换就可以了,但对于写操作那肯定需要调用operator=,就可以据此来判断读写,从来决定String是否需要重新生成实值。
 
       Proxy可以完成很多的工作,比如多维数组的实现,左值/右值的区分,压抑隐式性别转换。但Proxy也不是万能的,就如同Smart Pointer永远不是原生指针,Proxy对象永远不是基本对象,所有不要期待Proxy对象能完成基本对象所有的功能。在Proxy对象实现的过程当中,事实上是有很多工作要做的。这带来很多其他的问题,比如Debug上的困难。当两者差异不是关键的时候,Proxy能带来极大的好处。这真是一把双刃剑。我的原则是除非好处多到无法拒绝,否则用最简单的办法写代码。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值