句柄类作用:
管理对象内存分配和处理对象复制
第一个例子:
class Point
{
public:
Point():m_x(1), m_y(1){}
Point( int x, int y ): m_x(x), m_y(y){}
//复制构造函数和赋值操作符依靠编译器默认定义
int GetX(){ return m_x; }
int GetY(){ return m_y; }
Point& SetX( int& x ){ m_x = x; return *this; }
Point& SetY( int& y ){ m_y = y; return *this; }
private:
int m_x;
int m_y;
};
class Handle;
class UPoint
{
public:
friend class Handle;
UPoint(): m_Point(0, 0), m_Count(1){}
UPoint( int x, int y ): m_Point(x, y), m_Count(1){}
UPoint(Point& _rP): m_Point(_rP), m_Count(1){}
private:
Point m_Point;
int m_Count;
};
class Handle
{
public:
Handle():m_pUPoint(new UPoint()){}
Handle(int x, int y): m_pUPoint(new UPoint(x, y)){}
Handle(Point& _rP): m_pUPoint(new UPoint(_rP)){}
Handle(Handle& _rH): m_pUPoint(_rH.m_pUPoint){ ++(_rH.m_pUPoint->m_Count); }
Handle& operator= ( Handle& _rH )
{
//直接增加右边对象的计数
//算是优化技巧一种
++(_rH.m_pUPoint->m_Count);
//自身对象计数量
if( --m_pUPoint->m_Count == 0 )
delete m_pUPoint;
m_pUPoint = _rH.m_pUPoint;
return *this;
}
~Handle()
{
if( --m_pUPoint->m_Count == 0 )
delete m_pUPoint;
}
private:
UPoint* m_pUPoint;
};
这个用了一个class UPoint来管理对象(Point)和计数器(m_Count)。
所以缺点显而易见,不可能每个对象(这里指的是其他需要句柄的类)都需要class UPoint类来管理计数器(m_Count)和对象(Point)。
而且重要的是,如果对象Point万一派生了一个DerviedPoint对象时,class UPoint不是就要重写了?
所以便有了第二个例子
class Point
{
public:
Point():m_x(0),m_y(0){}
Point(int x, int y): m_x(x),m_y(y){}
//复制构造和赋值操作符,直接依靠编译器默认定义。
int GetX(){ return m_x; }
int GetY(){ return m_y; }
Point& SetX(int& x){ m_x = x; return *this; }
Point& SetY(int& y){ m_y = y; return *this; }
private:
int m_x;
int m_y;
};
class Handle
{
public:
Handle():m_pPoint(new Point(0, 0)), m_pCount(new int(1)){}
Handle(Point& _rP):m_pPoint(new Point(_rP)), m_pCount(new int(1)){}
Handle(int x, int y):m_pPoint(new Point(x, y)), m_pCount(new int(1)){}
Handle(const Handle& _rH): m_pPoint(_rH.m_pPoint), m_pCount(_rH.m_pCount){ ++*_rH.m_pCount; }
Handle& operator= ( Handle& _rH )
{
//直接先增加右边的对象计数器
//算是技巧的一种吧
++*_rH.m_pCount;
//Handle自身创建
if( --*m_pCount == 0 )
{
delete m_pCount;
delete m_pPoint;
}
m_pPoint = _rH.m_pPoint;
m_pCount = _rH.m_pCount;
return *this;
}
~Handle()
{
if( --*m_pCount == 0 )
{
delete m_pCount;
delete m_pPoint;
}
}
private:
Point* m_pPoint;
int* m_pCount;
};
好这个例子去掉了管理类class UPoint。
转而将对象(Point)和计数器(m_pCount)放在了Handle中。
也解决了对象(Point)继承问题。
视乎没什么问题了。
但是转头想想。
你妹,我要的是Handle,不要计数器。
我只是需要一个处理对象(Point)内存分配和对象(Point)复制的Handle类,干嘛要去管理繁琐的计数器问题。
为何不让计数器成为单独的类,只让句柄类处理内存和复制。
第三个例子
class Point
{
public:
Point():m_x(0), m_y(0){}
Point(int x, int y):m_x(x), m_y(y){}
//复制构造函数和拷贝构造函数实现,依赖编译器
int GetX() { return m_x; }
int GetY() { return m_y; }
Point& SetX( int& x ){ m_x = x; return *this; }
Point& SetY( int& y ){ m_y = y; return *this; }
private:
int m_x;
int m_y;
};
class UseCount
{
public:
UseCount(): m_pCount(new int(1)){}
UseCount( const UseCount& _rUC ): m_pCount(_rUC.m_pCount){ ++*_rUC.m_pCount; }
~UseCount(){ if(--*m_pCount == 0) delete m_pCount; }
//额外成员函数
//
//检测计数器是否只有一的对象
bool only(){ return *m_pCount == 1; }
//取代了operator=操作符
bool reattach( const UseCount& _rUse )
{
++*_rUse.m_pCount;
if( --*m_pCount == 0 )
{
delete m_pCount;
m_pCount = _rUse.m_pCount;
return true;
}
m_pCount = _rUse.m_pCount;
return false;
}
private:
//只声明不实现
UseCount& operator= (UseCount& _rUse);
int *m_pCount;
bool m_isNull;
};
class Handle
{
public:
Handle(): m_pPoint(new Point()){}
Handle(int x, int y): m_pPoint(new Point(x, y)){}
Handle(Point& _rPoint): m_pPoint(new Point(_rPoint)){}
Handle(Handle& _rH):m_pPoint(_rH.m_pPoint),m_Use(_rH.m_Use){}
~Handle(){ if(m_Use.only()) delete m_pPoint; }
Handle operator= ( Handle& _rH )
{
if( m_Use.reattach(_rH.m_Use) )
delete m_pPoint;
m_pPoint = m_pPoint;
return *this;
}
private:
UseCount m_Use;
Point* m_pPoint;
};
而Handle类就成为了只处理内存和复制。
这里略去了关于怎么样用Handle修改Point对象成员变量才算是合理。
以后再说。
参考资料《C++沉思录》第六章与第七章。