C ++ - 更快地向下转换树节点的子节点?

时间:2011-01-26 16:13:24

标签: c++ downcast

我有一个简单的层次结构树结构,其基类Node代表一个节点。节点可以是另一种特定类型(子类化)。

class Node {
  vector<Node*> childs;
  // simple node manipulation methods
  const vector<Node*>& getChildren() { return childs; }
}

我有几个Node的子类:

class FacultyNode : public Node; ...
class DepartmentNode : public Node; ...

假设我知道教师节点的所有孩子都是DepartmentNode类型,为了保存开发人员的工作,我打算做类似的事情

vector<DepartmentNode*> FacultyNode::getDepartments() {
  vector<Node*> tmp = this->getChildren();

  vector<DepartmentNode*> a;
  a.reserve(tmp.size());
  for (int i = 0; i < tmp.size(); i++) {
    a.push_back(static_cast<DepartmentNode*>(tmp[i]));
    }
    return a;
}

但这需要O(n),每次调用时都会创建新的矢量对象。

有没有更好的方法呢?

3 个答案:

答案 0 :(得分:4)

你真的需要复制载体吗?如果你不需要,你可以编写一个迭代器,当用户请求项目时,即在操作符*上进行转换。

MyIterator FacultyNode::getDepartmentsBegin() {
  vector<Node*>& tmp = this->getChildren();
  return MyIterator(tmp.begin());
}
MyIterator  FacultyNode::getDepartmentsEnd() {
  vector<Node*>& tmp = this->getChildren();
  return MyIterator(tmp.end());
}

struct MyIterator {
  vector<DepartmentNode*>::iterator m_it;

  MyIterator(vector<DepartmentNode*> it) : m_it(it) {}

  Department * operator*() { return (Department*)*it; }

  void operator++() { m_it++; }

  // in the same way, forwarding to m_it, implement other needed iterators.
  // ...
};

希望它澄清我的意思。

答案 1 :(得分:1)

也许您可以将Node变成模板?

template<typename T>
class Node {
  vector<T*> childs;  // I think a Boost.PtrContainer would be better
  // simple node manipulation methods
  const vector<T*>& getChildren() { return childs; }
}
class FacultyNode : public Node<DepartmentNode>;

答案 2 :(得分:0)

正如James McNellis在下面的评论中指出的那样,以下是不安全的(他更加明确)。我不会自己使用它,即使我不知道为什么它会引发未定义的行为 - 也许我应该ask this in a question


由于您在数组中存储指针,并假设您可以更改函数的返回类型,那么您可以这样做:

const vector<DepartmentNode*>* FacultyNode::getDepartments() {
  vector<Node*> tmp = this->getChildren();
  return reinterpret_cast<vector<DepartmentNode*>*>(&tmp);
}