C++重写的方法没有被调用

发布于 2024-08-05 07:21:56 字数 940 浏览 6 评论 0原文

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

我假设这是因为它正在转换RectShape,但我不知道如何阻止它这样做。我试图通过重写 Render 方法来让每个形状控制它的渲染方式。

关于如何实现这一目标有什么想法吗?

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;
};

Used like this:

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

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

This code ends up calling Shape::Render and not Rect::Render

I'm assuming this is because it is casting the Rect to a Shape, but I don't have any idea how to stop it doing this. I'm trying to let each shape control how it is rendered by overriding the Render method.

Any ideas on how to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

娇纵 2024-08-12 07:21:57

这是您的问题:

struct ShapePointPair {
        Shape shape;
        Point location;
};

您正在存储一个Shape。您应该存储一个 Shape * 或一个 shared_ptr 或其他东西。但不是 Shape; C++ 不是 Java。

当您将 Rect 分配给 Shape 时,仅复制 Shape 部分(这是对象切片) 。

Here's your problem:

struct ShapePointPair {
        Shape shape;
        Point location;
};

You are storing a Shape. You should be storing a Shape *, or a shared_ptr<Shape> or something. But not a Shape; C++ is not Java.

When you assign a Rect to the Shape, only the Shape part is being copied (this is object slicing).

梦回旧景 2024-08-12 07:21:57

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

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

This problem is called slicing - you lose the derived functionality when copying to a base.
To avoid this use pointers to the base class, i.e.

std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
千纸鹤带着心事 2024-08-12 07:21:57

问题是,在您的向量中,您存储的是 Shape 对象的副本,并且复制 Shape 对象不会复制其派生类的数据或功能 - 您是 切片 多态性。

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

The problem is that in your vector you are storing copies of Shape objects, and copying a Shape object does not copy the data or functionality of its derived classes - you're slicing the polymorphism away.

Manage the objects using new and delete, and arrange for your vector to store pointers to them.

疏忽 2024-08-12 07:21:57

多态性仅适用于指向形状的指针,不适用于形状对象。

The polymorphism will only work from a pointer to a shape, not from a shape object.

撩人痒 2024-08-12 07:21:57

您正在直接访问形状对象,以便覆盖工作,您需要通过指针或引用访问该对象。

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

这样做意味着您必须监视内存管理 - 因此您可以在结构中使用智能指针
形状点对 {
智能指针形状;
点位置;
};

You are accessing the shape object directly for the override to work you need to access the object via a pointer or references.

For example when you assigne the Shape into the ShapePointPair the code will 'slice' the object and only copy the Shape bit into the ShapePointPair

Doing this will mean you have to watch memory management - so you could use a smart pointer in the struct
ShapePointPair {
smart_pointer shape;
Point location;
};

标点 2024-08-12 07:21:57

不,这不是铸造。

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

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

必须在结构的构造时设置此引用
形状点对。为此,向 ShapePointPair 添加一个构造函数
目的。它必须传递(新创建的)实例
矩形。

还要遵守内存管理职责(正确的
编写的析构函数等)。

No, it is not casting.

You can instead store a reference to baseclass Point:

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

This reference must be set at construction time for struct
ShapePointPair. Add a constructor to ShapePointPair for this
purpose. It must be passed (newly created) instances of
Rect.

Also observe the memory management responsiblities (proper
written destructors, etc.).

玻璃人 2024-08-12 07:21:57

我不确定能否解释清楚,因为我的英语很差。

我认为你应该使用它的引用或指针类型。
因为形状准确地定义了它必须做什么。

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

使用指针或引用
像这样。

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:我个人使用抽象函数(virtual void Something() = 0;)。
因为有时我也忘记了它,所以我将其捕获为语法错误。

I'm not sure to explain well because of my english is poor.

I think you should have to use it reference or pointer type.
because shape is exactly defined what it has to do.

If you use your code directly, your child try to copy and do shape's working.
That is why doesn't work your override function.

use pointer or reference
like this.

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: personally i use abstract function(virtual void something() = 0;).
because i also forgot about it sometimes so i catch it as syntax error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文