C++ переопределяет переменную-член (std::vector)

вот классы, о которых мой вопрос

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. #P3#
    #P4#
  2. #P5#
    #P6#

И есть проблема, которую я действительно хочу как-то обойти.

В классе TransformationNode я сделал много (ИМХО) приведения типов, которых можно избежать, из базового класса в производный. Я точно знаю, что все элементы в векторе mNodeList являются TransformationNodes, но для обработки mNodeList мне нужно привести их тип.

Наследование правильное. Я имею в виду, что TransformationNode является узлом

mNodeList содержит дочерние узлы узла и не может иметь копию в производном классе, который содержит приведенную версию узлов
< br> И, наконец, я могу даже использовать reinterpered_cast, если static_cast дороже. Можете ли вы сообщить мне стоимость этих операций? они действительно большие проблемы с производительностью?
assert (dynamic_cast)... меры предосторожности уже приняты.



Вкратце, я хочу, чтобы мой компилятор знал, что mGraph на самом деле является SceneGraph*, а mNodeList содержит TransformationNode*, это помогает мне избежать потери приведения типов.


Спасибо, что уделили время


person Cihan    schedule 14.01.2012    source источник
comment
Я бы просто переместил переменную mNodeList из базового класса в производные классы. Это дает вам ту же функциональность без приведения   -  person Seth Carnegie    schedule 15.01.2012
comment
Странно, что Node содержит список еще... узлов. Я думаю, что редизайн решит большинство проблем здесь.   -  person Kerrek SB    schedule 15.01.2012
comment
@KerrekSB Я думаю, это дочерние узлы или что-то в этом роде.   -  person Seth Carnegie    schedule 15.01.2012
comment
@SethCarnegie: Но вот что не работает: если это дочерние узлы, и каждый дочерний узел может быть произвольным узлом, то вы не можете просто статически привести их к одному конкретному узлу. Либо состав неправильный, либо дерево - ложь...   -  person Kerrek SB    schedule 15.01.2012
comment
@KerrekSB да, я не подумал об этом, когда опубликовал свой первый комментарий, так что теперь он недействителен   -  person Seth Carnegie    schedule 15.01.2012


Ответы (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;
};

Поместите весь интерфейс в базовый класс, но реализуйте его только в каждом конкретном классе.

person Kerrek SB    schedule 14.01.2012