C++ 重写方法
我不明白这是怎么回事。
我有一个场景类,它有一个实体向量,并允许您从场景中添加和获取实体:
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; };
};
然后我有一个继承自实体的多边形类:
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业务。
I can't figure out what is up with this.
I have a Scene class that has a vector of Entities and allows you to add and get Entities from the 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();
};
My Entity class is as follows (output is for testing):
class Entity {
public:
virtual void draw() { cout << "No" << endl; };
};
And then I have a Polygon class that inherits from Entity:
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
};
As you can see, it has a draw() method that should override the draw() method it inherits from the Entity class.
But it doesn't. When using the following code:
scene->getEntity(0).draw();
where entity 0 is a Polygon (or at least should be), it prints "No" from the parent method (as though it's not a Polygon, just an Entity). In fact, it doesn't seem to let me call any methods unique to Polygon without getting:
'some method name' : is not a member of 'Entity'
So any idea what's up?
Thanks for the help.
UPDATE:
So I've implemented the code given in the first answer, but I'm not sure how to add my polygon to the list. Something like this?
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);
I'm just not used to this shared_ptr business.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我认为你需要发布你的调用代码,但本质上的问题是这样的。
您有一个从另一个具体类
Entity
派生的具体类Polygon
。 您的 addEntity 和 getEntity 函数采用并返回一个Entity
按值,因此,如果您尝试传入或检索Entity
,您将仅复制该对象的Entity
部分(对其进行切片)以及有关该对象的派生部分的信息将丢失。此外,您还有一个
Entity
的向量
,它是基类对象的向量,因此您无法存储除对象的基本类型之外的任何内容。如果您需要拥有混合类型对象的集合,但全部派生自
Entity
,则可能需要使用动态创建的对象和某种智能指针,例如tr1:: Shared_ptr 或
boost::shared_ptr
。例如
编辑
您更新的调用代码本质上是正确的,尽管使用对共享指针的本地常量引用有点晦涩。
我可能会选择类似的东西:
I think that you need to post your calling code, but the essentially problem is this.
You have a concrete class
Polygon
deriving from another concrete classEntity
. Your addEntity and getEntity functions take and return anEntity
by value so if you try to pass in or retrieve anEntity
, you will copy only theEntity
part of that object (slicing it) and the information about the derived part of the object will be lost.In addition you have a
vector
ofEntity
, which is a vector of base class objects, so you have no way of storing anything other than the base type of object.If you need to have a collection of a mixed type of objects, but all derived from
Entity
, you may need to use dynamically created objects and some sort of smart pointer such as atr1::shared_ptr
or aboost::shared_ptr
.E.g.
Edit
Your updated calling code is essentially correct, although using a local const reference to a shared pointer is a bit obscure.
I'd probably go with something like:
chollida 的评论是正确的:您将 Polygon 类型的对象推入用于 Entity 类型的内存位置,并遇到所谓的“切片”。 额外的“多边形”信息被切掉,剩下的就是实体。
在这些情况下,您应该存储指向基类的指针(或引用,如果可能)。
chollida's comment is correct: you're pushing an object of type Polygon into a memory location meant for types Entity, and running into what is called slicing. The extra 'Polygon' info gets sliced away and all you have left is the Entity.
You should store pointers (or references, if possible) to base classes in these situations.
为此,您应该使用纯虚函数。
然后从您的对象调用绘图函数,您还应该使用指向您的对象的指针。
You should use a pure virtual function for this.
Then call the draw function from your object, and you should also use pointers to your objects.
根据经验,在处理打算多态使用的对象时,应始终使用引用语义(即通过指针或引用访问对象)而不是值语义。
为了以这种方式确保安全,明智的做法是创建所有多态类型的基类 不可复制 通过创建私有复制构造函数和赋值运算符。 这将有效地防止切片,因为如果错误地使用值语义,代码将根本无法编译。
As a rule of thumb, you should always use reference semantics (i.e. access objects through pointers or references) instead of value semantics when dealing with objects you intend to use polymorphically.
To ensure safety in this manner, it is wise to make the base class of all your polymorphic types noncopyable by creating a private copy constructor and assignment operator. This will effectively prevent slicing as the code will simply fail to complile if value semantics are used by mistake.
您应该首先存储指向实体实例的指针(最好是智能指针:))。 Vector 在插入时会重新分配,因此即使在调用 getter 方法之前,您的对象也会被切片。
getter 方法的返回类型也应该是指针或引用,以便您能够进行多态调用。
You should store pointers (smart pointers :) preferably) to Entity instances in the first place. Vector is reallocating when inserting so your objects are sliced even before calling the getter method.
Return type for getter method should be also a pointer or a reference so you'll be able to make that polimorphic call.