2015-11-20 2 views
0

У меня есть класс, который является узлом дерева, называемым узлом. Мне нужно создать тип класса DerivedNode, который имеет некоторые дополнительные функции. Проблема в том, что Node имеет вектор Node * в качестве переменной-члена, поэтому, когда DerivedNode наследуется от Node, он наследует этот вектор. Я создал простой пример, показывающий вопрос:Удалить dynamic_cast в производном классе узла дерева

#include <iostream> 
#include <vector> 

class Node { 
public: 
    Node(int value_) : value(value_) {} 
    int foo() { return value; } 
    virtual void add(Node* new_node) { 
     children.push_back(new_node); 
    } 
protected: 
    std::vector<Node*> children; 
    int value; 
}; 

class DerivedNode : public Node { 
public: 
    DerivedNode(int value_) : Node(value_) {} 
    int bar() { return value*2; } 
    // Ensures we only add children of type DynamicNode* 
    virtual void add(DerivedNode* new_node) { 
     children.push_back(new_node); 
    } 
    void print() { 
     for (size_t i = 0; i < children.size(); ++i) { 
      std::cout << dynamic_cast<DerivedNode*>(children[i])->bar() << std::endl; 
     } 
    } 
}; 


int main() { 
    DerivedNode* child_a = new DerivedNode(5); 
    DerivedNode* child_b = new DerivedNode(6); 
    DerivedNode parent(1); 
    parent.add(child_a); 
    parent.add(child_b); 
    parent.print(); 
    delete child_a; 
    delete child_b; 
} 

Мой вопрос, как я могу сделать это без dynamic_cast? Мой фактический код намного сложнее, что означает, что во всем мире есть динамические броски.

+0

Я думаю, что дети DerivedNode должны находиться в 'std :: vector ', особенно если вы знаете, что он будет содержать только 'DerviedNode *'. – tforgione

+0

Добавить виртуальную функцию-член 'bar()' в базовый класс? – songyuanyao

+0

@DragonRock Я пробовал это, он создает много проблем намного хуже, чем dynamic_cast. Проблема в том, что есть два ребенка, поэтому методы в узле будут вызывать вектор , а методы в DerivedNode будут вызывать вектор version – texasflood

ответ

0

Первая функция добавления в производном классе абсолютно бесполезна, она не переопределяет функцию добавления из базового класса, она перегружает ее. Таким образом, вы все равно можете добавить Node * в производный класс. Чтобы предотвратить это, вы должны переопределить add (Node *) как закрытый.

Если вы не любите динамическое приведение, вы можете использовать статический бросок вместо или Вы можете иметь виртуальный бар в базовом классе, который ничего не делать или вы можете бросить сам (все это) вектор и назначить для ссылки или указателя на std :: vector DerivedNode *

0

Вы не можете иметь это в обоих направлениях. У вас либо есть принцип IS-A, отраженный в дизайне вашей классовой, либо нет. Если DerivedNode - это Node, то вектор Node s должен быть неотличим от вектора DerivedNode s - и никаких бросков не требуется. Если этого не может быть достигнуто, вы просто не можете использовать вектор базовых указателей.

Любой динамический_процесс в производственном коде для меня является жестким блоком для любого обзора, поскольку он явно нарушает основные принципы проектирования.