2009-08-04 242 views
7

我不明白這是什麼。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; }; 
}; 

然後我有從實體繼承的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是一個多邊形(或至少應該是),它打印「否」從父方法(就像它不是一個多邊形,只是一個實體)。事實上,它似乎並沒有讓我打電話到多邊形獨特的方法沒有得到:

一些方法名」:是不是「實體」

所以任何想法是怎麼回事的一員?

感謝您的幫助。

UPDATE:

所以我實現了在第一個答案給定的代碼,但我不知道如何將我的多邊形添加到列表中。像這樣?

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業務。

+1

嘗試存儲指向實體的指針,而不是您的Scene類中實體對象的副本。 – chollida 2009-08-04 21:27:58

回答

14

我認爲你需要發佈你的調用代碼,但實質上的問題是這樣的。

你有一個具體的類Polygon派生自另一個具體類Entity。您的addEntity和getEntity函數將返回Entity的值,因此如果您嘗試傳入或檢索Entity,則只會複製該對象的Entity部分(對其進行切片)以及有關該對象的派生部分的信息會迷路。

此外,你有一個vectorEntity,這是一個基類對象的向量,所以你沒有辦法存儲除基本類型的對象以外的任何東西。

如果你需要有一個混合型的對象的集合,而是全部來自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); 
+3

或者把它放在圖形上,發佈的代碼將一個Polygon放到一個實體大小的框中,但它並不全部適合。 – 2009-08-04 21:31:04

+0

用關於這個新代碼的問題更新了OP。 – 2009-08-04 21:56:45

1

chollida的評論是正確的:你推式多邊形的對象變成意味着實體類型的存儲位置和運行進入了所謂的切片。多餘的'Polygon'信息被切掉,你剩下的只是實體。

在這些情況下,您應該將指針(或可能的引用)存儲到基類中。

0

您應該首先將指針(智能指針:)存儲到實體實例中。插入時重新分配矢量,以便在調用getter方法之前切割對象。

getter方法的返回類型應該也是一個指針或引用,因此您可以進行該多態調用。

1

您應該爲此使用純虛函數。

class Entity 
{ 
public: 
    virtual void draw() = 0; 
}; 

然後從你的對象調用draw函數,你也應該使用指向你的對象的指針。

0

作爲一個經驗法則,在處理想要多態使用的對象時,應始終使用引用語義(即通過指針或引用訪問對象)而不是值語義。

爲了確保這種方式的安全性,通過創建私有拷貝構造函數和賦值操作符來創建所有多態類型的基類noncopyable是明智的。這將有效地防止切片,因爲如果錯誤地使用值語義,代碼將簡單地失敗。