У меня есть ситуация, когда я падаю из-за вышеупомянутой проблемы.Я хотел бы построить дерево со связанными узлами.Поскольку все деревья будут вести себя одинаково, но с разными типами, в духе наследования я хотел бы иметь возможность создавать деревья с разными типами, используя одну и ту же процедуру построения дерева, определенную базовым классом.Я хотел бы знать, что лучше всего подходит для моей ситуации.
struct Tree
{
struct Node { std::list<std::shared_ptr<Node>> children_; };
Tree()
{
root_ = CreateNode();
// carry on adding nodes to their parents...
}
virtual std::shared_ptr<Node> CreateNode() { return std::shared_ptr<Node>(new Node()); }
std::shared_ptr<Node> root_;
};
struct TreeDerived : public Tree
{
struct NodeDerived : public Tree::Node {};
TreeDerived() : Tree() {}
virtual std::shared_ptr<Node> CreateNode() { return std::shared_ptr<NodeDerived>(new NodeDerived()); }
};
Проблема в том, что я не могу вызывать производные функции до тех пор, пока не будет построена база (очевидно), и в ней используется базовая реализация CreateNode
метод, который всегда строит деревья с реализацией базового узла.Это означает, что я могу строить деревья, не задерживая их.Очевидное решение состоит в том, чтобы шаблон дерева мог принимать различные типы узлов, применяя тип узла с помощью черт?Однако это также означает, что определение всех методов должно быть в заголовке?Класс довольно мясистый, поэтому я хотел бы избежать этого, если это возможно, поэтому я подумал о передаче лямбды, которая делает это для меня.
struct Tree
{
struct Node { std::list<std::shared_ptr<Node>> children_; };
Tree(std::function<std::shared_ptr<Node>()> customNodeConstructor)
{
root_ = customNodeConstructor();
// carry on adding nodes to their parents... using the customNodeConstructor to create the nodes.
}
std::shared_ptr<Node> root_;
};
struct TreeDerived : public Tree
{
struct NodeDerived : public Tree::Node {};
TreeDerived(std::function<std::shared_ptr<Node>()> customNodeConstructor) : Tree(customNodeConstructor) {}
};
, которая позволяет мне выводить и передавать customNodeConstructor
, относящийся кпроизводное дерево.Безопасность типов частично обеспечивается, поскольку возвращаемый объект shared_ptr
должен быть производным от Tree::Node
, хотя не применяется к производному типу узла.
т.е. экземпляр TreeDerived
, который, возможно, должен использовать TreeDerived::NodeDerived
, принудительно должен использовать только Tree::Node
или производный тип, но не обязательно TreeDerived::NodeDerived
.
Затем это можно использовать следующим образом ...
Tree tree([]() { return std::shared_ptr<Tree::Node>(); });
TreeDerived treeDerived([]() { return std::shared_ptr<TreeDerived::NodeDerived>(); });
Это хорошая практика или я должен делать больше / что-то еще, не шаблонизируя объект Tree?
Большое спасибо.