第十章:一个课堂练习的分析(下)1
缺陷:浪费太多空间,而且本质上非常不灵活。
新设计方案与8章中所设计的表达式树非常相似。在类层次中反映出我们所操作的图象的结构,并将此结构保留下来以待今后所用。此外,我们还提供了一个句柄类,一则可以将我们使用继承的实现细节隐藏起来,二则可以省去用户处理内存管理的麻烦。
10-1策略
9章方案最大弊端:图象对象一旦生成,其结构信息立刻就丢失(为什么)。假如我们采用不同的策略,尽可能地保留结构信息,结果会怎么样?我们又该怎么做呢?能有什么好处?
第一个结论:就是我们可以存储几种不同的图象。一副图象的结构信息中最明显的方面就是一其构成方式:是从字符串中直接生成,还是加筐形成的,还是横向或者纵向连接而成的。
第二个结论:不必复制图象的内容了,假如我们将图象x加边框形成图象y,此操作并没有改动x,这就是说, y可以直接利用x而无需复制其内容。
Picture类中应包含一个指向其他类对象的指针;该对象应该表明其确切的图象种类。使用继承来组织和区分各种图象,就会产生这样的结构,Picture类包含一个(私有的)指针,指向一个我们称之为P_Node的类,这是一个抽象基类,有以下派生类。
String_Pic, 直接由字符串数组生成
Framed_Pic,
Hcat_Pic
Vcat_Pic
Picture 和P_Node类将协同解决内存分配的问题。
10-1-1 方案
class P_Node{};
class Frame_Pic:public P_Node{};
class String_Pic:public P_Node{};
class VCat_Pic:public P_Node{};
class Hcat_Pic:public P_Node{}
class P_Node;
class Picture {
friend ostream& operator<
friend Picture frame(const Picture&);
friend Picture operator&(const Picture&, const Picture&);
friend Picture operator&|(const Picture&, const Picture&);
public:
Picture();
Picture(const char* const*, int);
Picture(const Picture&);
~Picture();
Picture& operator=(const Picture&);
private:
P_Node* p;
};
10-1-2 内存分配
多个Pictuer可以指向同一个P_Node,应该引用计数。
class P_Node {
friend class Picture;
private:
int use;
};
Picture::Picture(const Picture& orig):p(orig.p)
{
orig.p->use++;
};
Picture::~Picture()
{
if(--p->use == 0)
delete p;
}
Picture& Picture::operator=(const Picture& orig)
{
orig.p->use++;
if(--p->use == 0)
delete p;
p=orig.p;
return *this;
}
class P_Node {
friend class Picture;
protected:
P_Node();
virtual ~P_Node(); //为什么
private:
int use;
};
P_Node::~P_Node() {}
P_Node::P_Node():use(1) {}
10-1-3 结构构造
如何构造表示不同图象的Picture对象的时候了?
我们已经决定构造函数生成一个String_Pic对象,并将其地址存储在Picture中。
Picture:Picture(const char* const* str, int n):
p(new String_pic(str, n)) {}
class String_Pic: public P_Node {
friend class Picture;
String_Pic(const char* const*, int);
~String_Pic();
char** data;
int size;
};
String_Pic::String_Pic(const char* const* p, int n):
Data(new char* [n]), size(n)
{
fir(int i = 0; i < n; i++) {
data[i] = new char[strlen(p[i])+1];
strcpy(data[i], p[i]);
}
}
String_Pic::~String_Pic()
{
for(int i = 0; i < size; i++)
delete[] data[i];
delete [] data;
}
class Frame_Pic:public P_Node
{
friend Picture frame(const Picture&);
Frame_Pic(const Picture&);
Picture p; //为什么?
}
Frame_Pic::Frame_Pic(const Picture& pic):p(pic) {}
Picture frame(const Picture& pic)
{
Frame_Pic* p = new Frame_Pic(pic);
// 现在如何?
}
创建了指针p,指向新创建的Frame_Pic对象,应当如何将这个指针加入一个Picture中,以便把这个Picture对象返回给用户呢?
可以回头修补,给Picture类增加一个私有构造函数。(为什么私有)。
Picture::Picture(P_Node* p_nide):p(p_node) {}
现在可以完成frame函数了。
Picture frame(const Picture&pic)
{
return new Frame_Pic(pic);
}
class Vcat_Pic: public P_Node {
friend Picture operator&
(const Picture&, const Picture&);
Vcat_Pic(const Picture&, const Picture&);
Picture top, bottom;
};
class Hcat_Pic:public P_Node {
friend Picture operator|
(const Picture&, const Picture&);
Hcat_Pic(const Picture&, const Picture&);
Picture left, right;
};
Vcat_Pic::Vcat_Pic(const Picture& t, const Picture& b) :
top(t), bottom(b) {}
Picature operator&(const Picture& t, const Picture& b)
{
return new Vcat_Pic(t, b);
}
Hcat_Pic::Hcat_Pic(const Picture& l , const Picture& r):
left(l), right(r) {}
Picture operator|(const Picture& l , const Picture& r)
{
return new Hat_Pic(l, r);
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/409557/viewspace-892091/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/409557/viewspace-892091/