第八十二讲 对象池(1)

如果说昨天的内容有些难以理解,看得云里雾里似懂非懂的话,那么接下来的内容大家一定会找回自信,C++难学这是业界公认了的,所以就算我们暂时理解不过来这些让人头晕脑胀的设计模式,但没关系,读书百遍其意直见,多读几遍就能够明白其中道理了,现在让我们来看一个问题。

在我们编写程序中,当然是大型的程序(C++也只有在大型程序中才能够体现出他存在的价值),我们可能需要面对各色各样的类型,各种各样的抽象,所以我们可能需要管理各种各样的对象,那么释放这些各种各样的对象成为一件难事,为什么这么说?因为C++可以保证不会有内存泄漏,可以在时间和空间上做到极限(当然这不是每个人都能够做到的),所以要是有对象没有得到释放那将会造成内存泄漏,那么解决这个问题将会是我们面临着的难题,第一眼,我们大概知道用什么来实现了,我们可能想到的是链表,是的,我们可以将各种对象放进链表之中,当我们要退出程序的时候销毁这个链表,所有的对象都会随之销毁,但是又有一个难题摆在我们的面前:
————————–
list<T>_list;


————————–
如果我们要使用链表来储存对象的话,我们面临着一个棘手的难题,如同上面一样,所有的对象似乎都要和T有点关系,至少也要由T派生而来,就算如此,我们还是得改写一下:
————————–
list<T*>_list;


————————–
现在我们至少是理清了一些思路——多重继承。
ok,我们现在先将list抛开,头多重继续开始,我们从头来理一下思路,要保证所有的对象被同时销毁,我们要做的是先来跟踪这些对象,还是那句话,C++的基本原则就是用类来表示概念,假如我们用ObjPool来跟踪各种各样的对象:
————————-
class ObjPool{

/////

////
};


ObjPool o;


————————-

o是ObjPool的对象,o跟踪着我们的所有需要管理的对象,当我们的对象o销毁时所有的对象都会得到销毁,这就意味着ObjPool的析构函数里面必定能够销毁各种对象,当然这句话换过来说有另外一层意思,当我们创建一个对象(当然不是ObjPool),我们可以这么说:我们在o中分配一个对象,比如是T,那么,我们可以这么分配:
—————————
T* _tp = new(o) T;


—————————

到现在来说,这个分配方式对于我们来说还是有些陌生,当然如果你们在其他书上见识过的话也就不足为奇了,但至少在我们这个课堂里面,想必大家还没见过(因为我到现在还没说过,哈哈),其实这也没啥好难的,为了让上面的表达式凑效,我们只需要给T重载一个operator new,将ObjPool作为参数:
————————————-
void* T::operator new(size_t,ObjPool&

);


————————————-
嗯,这个方案显得有些奇怪,如果说我们只是想要让一个对象能够在ObjPool中分配对象,那么我们不得不修改原本已经定义好的类,对于我们将要新写的class那没问题,所以这样做显得有些不合适,那么有没有办法可以避免我们去修改原本就已经存在的类呢???
当然解决这个问题的方案就是我们所说的继承,我们使用继承和一个间接层就可以将任何对象放入ObjPool中,而且通过多重继承我们可以在不用修改那些已经定义好的类的定义,就能完成我们想要的结果,不过这样做之前,我们得先得定义一个基类,ok,先假设这个基类叫ObjPoolItem:
————————————
class ObjPoolItem{
public:

void* operator new(size_t,ObjPool&

);



///////
};


————————————

我们将operator new操作符放进这个基类,但是C++有个限制:如果我们在自定义的类中重载了一个new操作符,就得保证该class中至少有一个只带一个参数的new操作符,因为只有这样才能保证这个类的对象可以用普通的new来分配和创建对象,当然我们也不想要这样做,就算是我们想要:
————————————-
ObjPoolItem* _op = new ObjPoolItem;


————————————-
我们也不该这么做,要做我们也该把他分配在ObjPool中,那么上面的代码是不该通过编译的,想要做到這一点很简单,我们将new操作声明为private,但是这样一来我们想要将ObjPoolItem对象分配在ObjPool中的话,我们必须得将ObjPool作为ObjPoolItem的友元类,还有由于我们的对象是分配在ObjPool中,所以对于ObjPoolItem的析构函数我们不能声明为共有的,为了能够创建对象,我们还得声明一个默认的构造函数,但是我们不想要拷贝和赋值操作,所以我们将他私有:
————————————
class ObjPoolItem{

friend class ObjPool;


public:

ObjPoolItem();


void* operator new(size_t,ObjPool&

);


protected:

virtual ~ObjPoolItem(){ }
private:

void* operator new(size_t);



ObjPoolItem(ObjPoolItem&

);



ObjPoolItem&

operator=(const ObjPoolItem&

);


};


————————————

关于这个基类我们先这样吧,我们回头来看看ObjPool,当然这个问题今天先不说了,留给大家去思考,接下来我们需要在ObjPool里添加些什么。


==============================
回复D直接查看目录

原文始发于微信公众号(

C/C++的编程教室

):第八十二讲 对象池(1)

|

发表评论