C++ override a member variable (std::vector)

1.5k views Asked by At

here are the classes which my question is about

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;    
}

First of all, I want to talk about the problems I solved. They may helps others. And you can confirm me if I am right ^^

  1. Can I override a function with a different return type ?
    Node* getNode(int index) became TransformationNode* getNode(int index)

    Yes as long as return types are covariant : http://www.tolchz.net/?p=33

  2. Can I override a member ?

    I don't know about overriding but a variable with the same name in the derived class will hide the one in the base class

And there is the problem I really want to get around some how

In the TransformationNode class I did many (IMHO) avoidable type casting from base class to derived one. I definitely know that all the elements in the mNodeList vector are TransformationNodes but to process mNodeList I have to type cast them.

The inheritance is correct I mean TransformationNode is a Node

mNodeList holds child nodes of the node and it can not have a copy in the derived class which holds typecasted version of Nodes

And finaly I can even use reinterpered_cast if static_cast is more costly. Can you inform me about cost of these operations ? are they really big performance issues ?
assert (dynamic_cast)... kind of precaution has already been taken.



briefly I want my compiler to know that mGraph is actually a SceneGraph* and mNodeList holds TransformationNode* this helps me to avoid lost of type casting.


Thank you for taking your time

1

There are 1 answers

0
Kerrek SB On

1) is correct, you can indeed override (virtual!) base functions if the return type is more derived.

Ad 2): indeed, you cannot "override" members. Redesign the base class if you need more flexible overridable behaviour.

static_cast is a static operation that is resolved at compile time, so much like reinterpret_cast it doesn't have any "cost".


As @Seth suggests in the comment, it might be an option to move the container. Ask yourself, can there ever be an abstract Node, or is every node actually of some derived concrete type? Perhaps you could make Node abstract:

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;
};

Put the entire interface into the base class, but only implement it in each concrete class.