C++如何覆盖成员变量(std::vector)?

3

这里是我所询问的类:

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. 我可以用不同的返回类型覆盖一个函数吗?
    Node* getNode(int index) 变成 TransformationNode* getNode(int index)

    是的,只要返回类型是协变的: http://www.tolchz.net/?p=33

  2. 我可以覆盖一个成员吗?

    我不知道是否可以覆盖,但派生类中具有相同名称的变量将隐藏基类中的变量

以下是我真正想要解决的问题

在TransformationNode类中,我进行了许多(在我看来)可避免的从基类到派生类的类型转换。我绝对知道mNodeList向量中的所有元素都是TransformationNodes,但是为了处理mNodeList,我必须进行类型转换。

继承是正��的,我的意思是TransformationNode是一个Node

mNodeList保存节点的子节点,不能在派生类中拥有一个副本,该副本保存了节点的类型转换版本

最后,如果static_cast更昂贵,我甚至可以使用reinterpered_cast。您能告诉我这些操作的成本吗?它们是否真的会影响性能?
assert(dynamic_cast)...已经采取了预防措施。



简而言之,我希望编译器知道mGraph实际上是SceneGraph*,mNodeList保存TransformationNode*,这有助于我避免类型转换丢失。


感谢您抽出时间


我会将变量mNodeList从基类移动到派生类中。这样可以在不需要转换的情况下获得相同的功能。 - Seth Carnegie
1
很奇怪一个 Node 包含了更多的节点列表。我认为重新设计可以解决大部分问题。 - Kerrek SB
1
@KerrekSB 我猜那些是子节点或者什么的。 - Seth Carnegie
@SethCarnegie:但这就是出了问题的地方:如果它们是子节点,并且每个子节点都可以是任意节点,那么你不能只将它们静态转换为一个特定的节点。要么转换是错误的,要么树是虚假的... - Kerrek SB
@KerrekSB,是的,当我发表第一条评论时没有考虑到这一点,所以现在它已经无效了。 - Seth Carnegie
1个回答

1

1)是正确的,如果返回类型更具体,您确实可以覆盖(虚拟!)基函数。

2)确实,您无法“覆盖”成员。如果需要更灵活的可重写行为,请重新设计基类。

static_cast 是一个在编译时解析的 静态 操作,因此与 reinterpret_cast 一样,它没有任何“成本”。


正如@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;
};

将整个 接口 放入基类中,但仅在每个具体类中实现它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接