C ++ Производственный класс, который самообновления
-
29-09-2019 - |
Вопрос
Так что предположим, у меня есть класс дерева в C ++
class Node{
void addChild(Node*);
/*obvious stuff*/
protected:
Node* parent;
vector<Node*> children
}
class specialNode : public Node{
void addChild(specialNode*);
/*obvious stuff*/
/*special stuff*/
}
Теперь, когда я получаю доступ к детям в специальностях, я, очевидно, получаю узел *, а не специальный воск *.
Но этот специальный совет * имеет переменные элемента и функции, которые узел не имеет.
Я могу заставить специального фундамента, чтобы принять специальный совет только как дети, и в противном случае пробил время компиляции, но я все еще получаю узел * при доступе к детям / родителю, и я должен бросить его, когда я хочу использовать специальные функции, даже в специальных функциях.
Есть ли умный или просто любой лучший способ пойти об этом? Кроме буквально кастинга каждый раз?
Решение
Если вам нужно только SpecialNode
объекты в вашем дереве (и просто хотите инкапсулировать все общие функциональные возможности деревьев в Node
) ты можешь сделать Node
так называемый «смеси в классе, как
template <class N>
class Node : public N {
public:
void addChild(Node<N>*);
protected:
Node<N>* parent;
vector<Node<N>*> children;
};
class SpecialNodeBase {
// Here comes all "special" data/methods for your "special" tree
};
typedef Node<SpecialNodeBase> SpecialNode;
После этого вы можете построить дерево SpecialNode
объекты и используют все методы от SpecialNodeBase
а также дополнительные функции управления деревьев Node
Другие советы
Поскольку функция Addchild в вашем классе дочернего класса не является полиморфизмом, делает его виртуальным, но функции перегрузки через базовые / члены ребенка не допускаются, поэтому мы должны изменить параметр Addchild в классе ребенка:
class Node{
virtual void addChild(Node*);
...
}
class specialNode : public Node{
virtual void addChild(Node*);
...
}
Теперь он должен работать.
Если вы хотите получить доступ к childeren
Переменная от дочернего класса (specialNode
Класс), вы должны бросить его. Например:
specialNode* var = static_cast<specialNode*>(children[i]);
Так как мы объявили Addchild как виртуальную функцию, то мы должны использовать dynamic_cast
вместо static_cast
Если мы не уверены, что children[i]
всегда является примером specialNode
класс, и, таким образом, лучше использовать dynamic_cast
:
specialNode* var = dynamic_cast<specialNode*>(children[i]);
if(var != NULL)
{
//...
}
Если я правильно понимаю, «Mix-In Class Solution не позволит вам позвонить addChild
из функций, реализованных SpecialNodeBaseClass
.
Вы можете сделать следующее:
template <class recursiveT>
class Base {
public:
Base(dataType data) { populate children with data; }
void addChild() { something base class appropriate; }
protected:
std::vector<recursiveT> children;
};
class Derived: public Base<Derived> {
public:
/* note: the constructor here will actually call the
constuctor of the base class */
Derived(dataType data) : Base<Derived>(data) {}
/* other special functions go here. */
};
Это может выглядеть немного сумасшедшим, но это чисто компилируется для меня на нескольких версиях GCC, поэтому я склонен верить, что это не совсем неправильно направляется. Теперь вы должны иметь возможность вызвать функции базы изнутри изнутри.
Вам определенно придется бросить Node *
к А. specialNode *
В какой-то момент, но вы можете сделать это чистое и легко управлять, делая это только в одном месте. Вы можете добавить функцию участника, скажем, getParent
и переопределить его в specialNode
, как это:
class Node {
...
virtual Node *getParent() {
return parent;
}
};
class specialNode : public Node {
...
specialNode *getParent() {
return dynamic_cast<specialNode *>(parent);
}
};
Конечно, это предполагает, что specialNode
у всегда есть другие specialNode
как родитель / дети. Если вы смешиваете Node
песок specialNode
S, это, очевидно, не будет работать.