我无法弄清楚这是怎么回事。
我有一个具有实体向量的Scene类,允许您从场景中添加和获取实体:
class Scene {
private:
// -- PRIVATE DATA ------
vector<Entity> entityList;
public:
// -- STRUCTORS ---------
Scene();
// -- PUBLIC METHODS ----
void addEntity(Entity); // Add entity to list
Entity getEntity(int); // Get entity from list
int entityCount();
};
我的实体类如下(输出用于测试):
class Entity {
public:
virtual void draw() { cout << "No" << endl; };
};
然后我有一个继承自Entity的Polygon类:
class Polygon: public Entity
{
private:
// -- PRIVATE DATA ------
vector<Point2D> vertexList; // List of vertices
public:
// -- STRUCTORS ---------
Polygon() {}; // Default constructor
Polygon(vector<Point2D>); // Declare polygon by points
// -- PUBLIC METHODS ----
int vertexCount(); // Return number of vertices
void addVertex(Point2D); // Add vertex
void draw() { cout << "Yes" << endl; }; // Draw polygon
// -- ACCESSORS ---------
Point2D getVertex(int); // Return vertex
};
如您所见,它有一个draw()方法,它应该覆盖它从Entity类继承的draw()方法。
但事实并非如此。使用以下代码时:
scene->getEntity(0).draw();
其中实体0是多边形(或至少应该是),它从父方法打印“否”(好像它不是多边形,只是一个实体)。实际上,似乎没有让我调用Polygon独有的任何方法而不会得到:
'某些方法名称':不是“实体”的成员
所以有什么想法吗?
感谢您的帮助。
更新
所以我已经实现了第一个答案中给出的代码,但我不确定如何将多边形添加到列表中。像这样的东西?
const tr1::shared_ptr<Entity>& poly = new Polygon;
poly->addVertex(Point2D(100,100));
poly->addVertex(Point2D(100,200));
poly->addVertex(Point2D(200,200));
poly->addVertex(Point2D(200,100));
scene->addEntity(poly);
我只是不习惯这个shared_ptr业务。
答案 0 :(得分:14)
我认为你需要发布你的调用代码,但基本上是问题。
您有一个具体的类Polygon
派生自另一个具体的类Entity
。您的addEntity和getEntity函数按值获取并返回Entity
,因此,如果您尝试传入或检索Entity
,则只会复制Entity
部分该对象(切片)和有关对象派生部分的信息将丢失。
此外,您有一个vector
Entity
,它是基类对象的向量,因此您无法存储除基础对象类型之外的任何内容。
如果您需要一个混合类型的对象的集合,但所有对象都来自Entity
,您可能需要使用动态创建的对象和某种智能指针,例如tr1::shared_ptr
或boost::shared_ptr
。
E.g。
class Scene {
private:
// -- PRIVATE DATA ------
vector< std::tr1::shared_ptr<Entity> > entityList;
public:
// -- STRUCTORS ---------
Scene();
// -- PUBLIC METHODS ----
void addEntity( const std::tr1::shared_ptr<Entity>& ); // Add entity to list
const std::tr1::shared_ptr<Entity> getEntity(int); // Get entity from list
int entityCount();
};
修改强>
您更新的调用代码基本上是正确的,尽管使用对共享指针的本地const引用有点模糊。
我可能会选择以下内容:
std::tr1::shared_ptr<Polygon> poly( new Polygon );
poly->addVertex(Point2D(100,100));
poly->addVertex(Point2D(100,200));
poly->addVertex(Point2D(200,200));
poly->addVertex(Point2D(200,100));
scene->addEntity(poly);
答案 1 :(得分:1)
chollida的评论是正确的:你将一个Polygon类型的对象推送到一个存储位置,用于实体类型,并运行到所谓的切片。额外的“多边形”信息会被切掉,您剩下的就是实体。
在这些情况下,您应该将指针(或引用,如果可能)存储到基类。
答案 2 :(得分:1)
你应该使用纯虚函数。
class Entity
{
public:
virtual void draw() = 0;
};
然后从您的对象调用draw函数,您还应该使用指向对象的指针。
答案 3 :(得分:0)
您应该首先将指针(智能指针:)存储到实体实例中。插入时向量会重新分配,因此即使在调用getter方法之前也会对对象进行切片。
getter方法的返回类型也应该是一个指针或引用,这样你就可以进行这种polimorphic调用。
答案 4 :(得分:0)
根据经验,在处理您打算多态使用的对象时,应始终使用引用语义(即通过指针或引用访问对象)而不是值语义。
为了确保以这种方式安全,最好通过创建私有拷贝构造函数和赋值运算符来创建所有多态类型noncopyable的基类。这将有效地防止切片,因为如果错误地使用了值语义,代码将无法完成编译。