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
方法让每个形状控制它的呈现方式。
关于如何实现这一目标的任何想法?
答案 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)
您可以尝试使用boost :: ptr_vector
http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
答案 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;)。 因为有时我也忘记了它,所以我将其捕获为语法错误。