C ++重写方法未被调用

时间:2009-09-18 11:41:56

标签: c++ inheritance virtual override

Shape.h

namespace Graphics {
    class Shape {
    public:
        virtual void Render(Point point) {};
    };
}

Rect.h

namespace Graphics {
    class Rect : public Shape {
    public:
        Rect(float x, float y);
        Rect();
        void setSize(float x, float y);
        virtual void Render(Point point);

    private:
        float sizeX;
        float sizeY;
    };
}

struct ShapePointPair {
    Shape shape;
    Point location;
};

像这样使用:

std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList();

for(int i = 0; i < theShapes.size(); i++) {
    theShapes[i].shape.Render(theShapes[i].location);
}

此代码最终会调用Shape::Render而不是Rect::Render

我假设这是因为它将Rect转换为Shape,但我不知道如何阻止它这样做。我试图通过覆盖Render方法让每个形状控制它的呈现方式。

关于如何实现这一目标的任何想法?

8 个答案:

答案 0 :(得分:21)

这是你的问题:

struct ShapePointPair {
        Shape shape;
        Point location;
};

您正在存储Shape。您应该存储Shape *shared_ptr<Shape>或其他内容。但不是Shape; C ++不是Java。

Rect分配给Shape时,只会复制Shape部分(这是对象切片)。

答案 1 :(得分:4)

此问题称为切片 - 在复制到基础时会丢失派生功能。 为避免这种情况,请使用指向基类的指针,即

std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);

答案 2 :(得分:2)

问题在于,在向量中存储Shape对象的副本,而复制Shape对象不会复制其派生类的数据或功能 - 您只需要slicing多态性。

使用new和delete管理对象,并安排vector存储指向它们的指针。

答案 3 :(得分:1)

多态性只能从指向形状的指针而不是形状对象。

答案 4 :(得分:1)

您正在直接访问形状对象以使覆盖工作,您需要通过指针或参考来访问该对象。

例如,当您将Shape分配到ShapePointPair时,代码将“切片”对象并仅将Shape位复制到ShapePointPair

执行此操作意味着您必须观察内存管理 - 因此您可以在结构中使用智能指针     ShapePointPair {            smart_pointer形状;             点位置;     };

答案 5 :(得分:0)

不,它不是在施法。

您可以改为存储对基类Point的引用:

struct ShapePointPair {
        Shape shape;
        Point &location;
};

此引用必须在struct的构造时设置 ShapePointPair。为此向ShapePointPair添加构造函数 目的。必须传递(新创建的)实例 矩形。

还要观察内存管理责任(正确 书面破坏者等。)。

答案 6 :(得分:0)

答案 7 :(得分:0)

由于我的英语不好,我不确定讲得很好。

我认为您应该使用它的引用或指针类型。 因为形状是精确定义的,所以必须做。

如果您直接使用代码,则您的孩子会尝试复制并制作形状。 这就是为什么您的覆盖功能不起作用的原因。

使用指针或引用 这样。

pointer.h

class Parent {
public:
    virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
    virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
    virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
    Parent* obj1;
    Parent* obj2;
};
int main() {
    Child1 child1;
    Child2 child2;
    Holder holder = { &child1, &child2 };
    holder.obj1->work();
    holder.obj2->work();
    return 0;
}

reference.h

class Parent {
public:
    virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
    virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
    virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
    Parent& obj1;
    Parent& obj2;
};
int main() {
    Child1 child1;
    Child2 child2;
    Holder holder = { child1, child2 };
    holder.obj1.work();
    holder.obj2.work();
    return 0;
}

* ps:我个人使用抽象函数(虚拟void something()= 0;)。  因为有时我也忘记了它,所以我将其捕获为语法错误。