今天上课偷偷看了几章,总结一下~
第五章 代理类
我们需要设计一个容器,有能力包含类型不同而彼此相关的对象,使用代理的方法来实现
而且surrogate是handle的基础
代理类的大致的框架是~
有一个父类,是一个抽象基类,并派生出子类,子类在父类的基础上派生出更多的功能,
我们的目的是要将不同的子类对象用一个容器来实现操作,
建立一个代理类,其中的一个成员变量是指向抽象基类的指针,
在建立容器时使用代理类
在继承和容器共用,迫使我们来处理两个问题,控制内存分配和把不同的类型和对象发在同一个容器中,采用基础的c++技术,用类来表示概念,我们可以兼顾着两个问题,做这些事的时候我们采取代理类,用这个类的每个对象都代表另一个对象,该对象可以是位于一个完整层次中的任何类的对象,通过在容器中用代理对象而不是对象本生的方式,解决了我们的问题。
第六章 句柄类
句柄类定义
句柄类(智能指针smart point)是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。
在C++中一个通用的技术是定义包装(cover)类或句柄(handle)类,也称智能指针。句柄类存储和管理基类指针。指针所指向对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用zi指针执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象类型而变化,即实现c++运行时动态绑定。故句柄用户可以获得动态行为但无需操心指针的管理。
句柄类实际上通过复制指向引用计数器类型的指针,来代替复制实际对象;从而使得复制对象变成复制指针,实现虚拟复制(即是用复制对象的地址代替复制对象本身),以提高内存效率和访问速度。在涉及到大型、复杂对象以及一些不能复制或是不易复制的对象的复制控制问题时,显得特别有用。
定义句柄类或智能指针的通用技术是采用一个使用计数(use count)。句柄类将一个计数器与类指向的对象相关联。使用计数跟踪该类有多少个指针共享同一对象。当使用计数为0时,就删除该类对象,否则再删除类对象时,只要引用计数不为0,就不删除实际的类对象,而是是引用计数减1,实现虚删除。
为了便于理解,我们定义一个实际类(Point),一个引用计数器类(UPoint),一个句柄类(Handle),后面将有例子给以参考。
实现使用计数有两种经典策略:一种是定义一个单独的具体的类用以封装使用计数和指向实际类的指针;
另一种是定义一个单独的具体的类用以封装引用计数和类的对象成员。我们称这种类为计数器类(UPoint)。在计数器类中,所有成员均设置为private,避免外部访问,但是将句柄类Handle类声明为自己的友元,从而是句柄类能操纵引用计数器。
写时复制(copy on write)技术是解决如何保证要改动的那个引用计数器类UPoint对象不能同时被任何其他的句柄类(Handle类)所引用。通俗的来说,就是当实际对象Point被多个Handle类的指针共享时,如果需要通过指针改变实际对象Point,而其他的指针又需要保持原来的值时,这就有矛盾了。打个不恰当的比方来说,两个以上的人共有5W块钱,如果其中一个人想用这5W块钱去消费,那就必须通知其他人。否则在这个人消费了5块钱后,其他人还以为他们仍然有5W块钱,如果这儿时候,他们去买5W的东西,就会发现钱变少了或是没有了,此时他们就陷入债务的泥团。在C++中通过指针访问已经删除或是不存在的对象,将是非常危险的。有可能系统提示该行为未定义,也有可以内存非法访问,还有可能使系统崩溃
网上down的程序
class Point
{
public:
Point(): xval(0), yval(0) {}
Point(int x, int y): xval(x), yval(y) {}
int x() const {return xval;}
int y() const {return yval;}
Point& x(int xv) {xval = xv; return *this;}
Point& y(int yv) {yval = yv; return *this;}
private:
int xval;
int yval;
};
//引用计数型句柄
class UPoint
{
private:
friend class Handle;
Point p;
int u; //计数器
UPoint(): u(1) {}
UPoint(int x, int y): p(x, y), u(1) {}
UPoint(const Point& p0): p(p0), u(1) {}
};
//句柄类
class Handle
{
public:
Handle(): up(new UPoint) {}
Handle(int x, int y): up(new UPoint(x, y)) {}
Handle(const Point& p): up(new UPoint(p)) {}
Handle(const Handle& h): up(h.up) {++up->u;}
Handle& operator=(const Handle& h)
{
++h.up->u;
if (--up->u == 0)
delete up;
up = h.up;
return *this;
}
~Handle()
{
if (--up->u == 0)
delete up;
}
int x()const
{
return up->p.x();
}
Handle& x(int x0)
{
up->p.x(x0);
return *this;
}
int y()const
{
return up->p.y();
}
Handle& y(int y0)
{
up->p.y(y0);
return *this;
}
private:
UPoint* up;
};
int main()
{
Handle h1;
Handle h2;
Handle h3;
h1.x(10);
cout<<h1.x()<<endl;
h2=h1;
cout<<h2.x()<<endl;
Sleep(10000);
return 0;
}