进行UI开发的过程中,考虑到用户可能会动态的向一个对象添加属性,或其他对象,可以通过树形结构来组织这个对象,所有可进行添加的对象都应该继承自一个父类。由于树形结构具有无限拓展的特性,拷贝树形对象变得麻烦,所以可以通过递归树来拷贝一个树形对象。
具体实现demo见代码:
#include <iostream>
#include <vector>
using namespace std;
//树形基类
class Node {
public:
Node() {}
//虚析构
virtual ~Node() {
for (int i = 0; i < NodeArray.size(); i++) {
delete NodeArray[i];//析构节点
//这里还要把 NodeArray[i] 从 NodeArray 中移除,以防影响递归
NodeArray[i] = nullptr;
}
}
string Name;
//节点数组
vector<Node*> NodeArray;
//添加节点
void AddChild(Node*child) {
NodeArray.push_back(child);
}
void RemoveChild(Node* child) {
//erase
for (int i = 0; i < NodeArray.size(); i++) {
if (NodeArray[i] == child) {
NodeArray.erase(NodeArray.begin() + i);
break;
}
}
}
void DeleteChild(Node* child) {
//delete
for (int i = 0; i < NodeArray.size(); i++) {
if (NodeArray[i] == child) {
delete child;
NodeArray.erase(NodeArray.begin() + i);
break;
}
}
}
};
//三个继承了Node的子类
class foo :public Node {
public:
foo(string name) {
Name = name;
}
};
class foo1 :public Node {
public:
foo1(string name) {
Name = name;
}
};
class foo2 :public Node {
public:
foo2(string name) {
Name = name;
}
};
//用已有的树形结构递归构造新的树形结构
void ConstructNode(Node * innode,Node*outnode) {
for (int i = 0; i < innode->NodeArray.size(); i++) {
Node* parent = innode->NodeArray[i];
Node* childnode = nullptr;
//将 if else 用 函数指针map代替
if (parent->Name == "foo") {
childnode = new foo("foo");
outnode->AddChild(childnode);
}
else if (parent->Name == "foo1") {
childnode = new foo1("foo1");
outnode->AddChild(childnode);
}
else if (parent->Name == "foo2") {
childnode = new foo2("foo2");
outnode->AddChild(childnode);
}
//递归调用
ConstructNode(innode->NodeArray[i], childnode);
}
}
//显示节点
void ShowNode(Node* innode) {
for (int i = 0; i < innode->NodeArray.size(); i++) {
Node* node = innode->NodeArray[i];
cout << node->Name << endl;
ShowNode(innode->NodeArray[i]);
}
}
int main()
{
Node* node = new Node();
node->AddChild(new foo("foo"));
node->AddChild(new foo1("foo1"));
node->AddChild(new foo2("foo2"));
foo2* f = new foo2("foo2");
f->AddChild(new foo("foo"));
f->AddChild(new foo1("foo1"));
f->AddChild(new foo2("foo2"));
node->AddChild(f);
Node* node2 = new Node();
ConstructNode(node, node2);
ShowNode(node);
delete node;
cout << "---------------------------\n";
ShowNode(node2);
delete node2;
}
虚析构是为了析构子对象,
由于树形对象具有析构子节点的能力,析构树时可以从任意节点开始析构,析构后要从数组中把对应的节点移除
移除子节点而不析构的话,把对应子节点的指针设为 nullptr,移除后要从数组中把对应的节点移除。当然前提是能自由访问到每个节点,否则子节点就访问不到了。