C ++重写方法

时间:2009-08-04 21:24:33

标签: c++ class inheritance methods override

我无法弄清楚这是怎么回事。

我有一个具有实体向量的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业务。

5 个答案:

答案 0 :(得分:14)

我认为你需要发布你的调用代码,但基本上是问题。

您有一个具体的类Polygon派生自另一个具体的类Entity。您的addEntity和getEntity函数按值获取并返回Entity ,因此,如果您尝试传入或检索Entity,则只会复制Entity部分该对象(切片)和有关对象派生部分的信息将丢失。

此外,您有一个vector Entity,它是基类对象的向量,因此您无法存储除基础对象类型之外的任何内容。

如果您需要一个混合类型的对象的集合,但所有对象都来自Entity,您可能需要使用动态创建的对象和某种智能指针,例如tr1::shared_ptrboost::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的基类。这将有效地防止切片,因为如果错误地使用了值语义,代码将无法完成编译。