2012-01-14 45 views
3

這裏有這我的問題是關於c + +重寫一個成員變量(標準::向量)

class Graph {} 
class SceneGraph : public Graph {} 

class Node { 
public: 
    virtual Node* getNode(int index) { return mNodeList[index]; } 

protected: 
    vector<Node*> mNodeList; 
    Graph* mGraph; 
} 

class TransformationNode : public Node { 
public: 
    TransformationNode* getNode(int index) { return static_cast<TransformationNode*> (mNodelist[index]); } 

    void _update() { 
     auto beg = mNodeList.begin(); 
     auto end = mNodeList.end(); 
     while (begin != end) { 
      TransformationNode* node = static_cast<TransformationNode*> (*beg); 
      node->_update(); 
     } 
    } 

private: 
    bool mUpdated; 
    SceneGraph* mGraph;  
} 

首先類,我想談談我解決了這個問題。他們可能會幫助別人。你能確認我,如果我是正確的^^

  1. 我可以覆蓋一個函數用不同的返回類型?
    節點* getNode(INT指數)成爲TransformationNode * getNode(INT指數)

    是隻要返回類型是協變:http://www.tolchz.net/?p=33

  2. 我可以覆蓋一員?

    我不知道,但覆蓋在派生類中的相同名稱的變量將隱藏一個基類

而且有問題我真的想解決一些如何

在TransformationNode類中,我做了許多(恕我直言)可避免的類型鑄造從基類到派生的。我肯定知道mNodeList向量中的所有元素都是TransformationNodes,但是要處理mNodeList,我必須輸入它們。

繼承是正確的我的意思TransformationNode是節點

mNodeList保存節點的子節點,它不能在保持節點

的類型強制轉換版本的派生類副本,並finaly我甚至可以用reinterpered_cast如果static_cast更昂貴。你能告訴我這些操作的成本嗎?他們真的是很大的性能問題嗎?
assert(dynamic_cast)...已經採取了一些預防措施。



簡要我希望我的編譯器知道mGraph實際上是一個場景圖*和mNodeList持有TransformationNode *這可以幫助我避免丟失的類型轉換。


感謝您抽出時間

+1

這裏發生了什麼 – 2012-01-14 23:56:08

+0

我只是將變量'mNodeList'從基類移動到派生類中。這給了你相同的功能,不需要鑄造 – 2012-01-14 23:56:42

+1

奇怪的是'Node'包含更多...節點的列表。我認爲重新設計可以解決這裏的大部分問題。 – 2012-01-14 23:57:32

回答

1

1)是正確的,你確實可以重寫(虛擬!)基函數如果返回類型較爲得出。

廣告2):的確,您不能「覆蓋」成員。如果您需要更靈活的可重寫行爲,請重新設計基類。

static_cast靜態操作,在編譯時得到解決,那麼像reinterpret_cast它不具有任何「成本」。


As @Seth在註釋中提示,它可能是移動容器的一個選項。問問自己,是否可以有抽象的Node,或者每個節點實際上是一些派生的具體類型?也許你可以讓Node摘要:

struct Node { Node * getNode(size_t index) const = 0; }; 

struct TransformNode : Node 
{ 
    TransformNode * getNode(size_t index) const { return m_nodes[index]; } 
private: 
    std::vector<TransformNode *> m_nodes; 
}; 

把整個接口成的基類,但只有落實到每一個具體的類。