2012-01-14 61 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; 
}; 

把整个接口成的基类,但只有落实到每一个具体的类。