我正在研究一种相当广泛使用虚拟类的图形应用程序 . 它有:
-
图片类,基本上是形状的集合 .
-
一个形状类,它纯粹是虚拟的,并且有一些继承自它的类:
-
圈
-
多边形
-
矩形
-
图形,任何图形图形(也是虚拟的),形状都继承自此 .
从本质上讲,我的问题归结为实现图片类,它基本上用于存储形状集合 . 我目前正在使用Vector来存储形状,但是,很明显这是错误的决定,因为Vector实例化了这些形状,这并不好,因为它们纯粹是虚拟的 .
下面是我目前的代码库(总结了一下):
class Figure {
public:
...
virtual ~Figure();
...
};
class Shape: public Figure
{
public:
...
virtual ~Shape() {}
virtual Shape* clone() const = 0;
...
};
class Polygon : public Shape
{
public:
...
virtual Shape* clone() const {return new Polygon(*this);}
...
private:
std::vector<Point> points;
};
class Picture: public Figure {
public:
...
Picture(Graphics& gd);
Picture (const Picture&);
~Picture();
void clear();
void add (const Shape&);
...
private:
std::vector<Shape> shapes;
Graphics* gfx;
};
//Picture implementation:
...
Picture::Picture(Graphics& gd)
{
gfx = &gd;
}
Picture::Picture(const Picture& a)
{
shapes = a.shapes;
}
Picture::~Picture()
{
clear();
}
void Picture::clear()
{
shapes.clear();
}
void Picture::add (const Shape& shp)
{
Shape* nshp = shp.clone();
shapes.push_back(*nshp);
}
...
我得到的错误消息只是其中的一小部分:
picture.cpp:33:从这里实例化/opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/ c /4.4.1/ext/new_allocator.h:105:错误:无法分配抽象类型'Shape'的对象shape.h:12:注意:因为以下虚函数在'Shape'中是纯粹的:shape.h: 58:注意:虚拟void Shape :: get(std :: istream&)shape.h:31:注意:虚拟void Shape :: put(std :: ostream&)const shape.h:36:注意:虚拟void Shape :: scale(const Point&,double)shape.h:40:注意:虚拟void Shape :: translate(double,double)shape.h:45:注意:虚拟void Shape :: reflectHorizontally(double)shape.h:49:note :virtual void Shape :: reflectVertically(double)shape.h:52:注意:虚拟RectangularArea Shape :: boundingBox()const shape.h:21:注意:虚拟Shape * Shape :: clone()const shape.h:55 :注意:虚拟void Shape :: draw(Graphics&)const
那么存储这些形状的理想方式是什么 . 我应该用什么样的收藏来存放这些东西?
谢谢
2 回答
当您需要多态时,您需要使用指针或引用 . 由于容器(或数组)无法存储引用,因此必须使用指针 .
基本上将您的图片类的向量更改为:
并适当修改其他成员函数 .
你可以将它们作为值类型存储的原因是因为vector是一个同质的容器,即它只存储一种类型的数据(并且只允许一种类型 - 不允许子类!) . 这是因为向量将其数据存储在一个数组中,该数组需要知道它们在数组中存储它们的对象的大小 .
如果将它们存储为指针,则它们都具有相同的大小(
sizeof(Shape*)
),并且还可以访问形状的vtable,这是允许多态行为的原因 .使用协变返回类型 . 有关
clone
方法,请参阅FAQ 20.8 . 您也可以依赖工厂方法来创建Shape
对象 .此外,您不能拥有抽象类对象的容器,抽象类无法实例化 . 相反,创建一个指向派生具体对象的指针/引用的容器 . 请注意,如果您使用指针,则清除它们是您的责任 . 容器不会正确地取消分配内存 . 您可以使用智能指针而不是原始指针来更有效地处理此问题 . 从Boost中查找
scoped_ptr
和shared_ptr
.