C++ C++;-更快地向下投射树节点的子节点?

C++ C++;-更快地向下投射树节点的子节点?,c++,downcast,C++,Downcast,我有一个简单的层次树结构,其中一个基类节点表示一个节点。节点可以是另一种特定类型(子类化) 假设我知道一个教员节点的所有子节点都是DepartmentNode类型,为了节省开发人员的工作,我打算这样做 vector<DepartmentNode*> FacultyNode::getDepartments() { vector<Node*> tmp = this->getChildren(); vector<DepartmentNode*> a;

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

假设我知道一个教员节点的所有子节点都是
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;
}
向量FacultyNode::getDepartments(){ 向量tmp=this->getChildren(); 载体a; a、 储备(tmp.size()); 对于(int i=0;i 但这需要
O(n)
,每次调用时都会创建新的向量对象

有更好的方法吗?

正如詹姆斯·麦克内利斯在下面的评论中指出的那样,以下是不安全的(他更直截了当)。我自己也不会使用它,即使我不知道为什么它会触发未定义的行为——也许我应该这样做


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

const vector<DepartmentNode*>* FacultyNode::getDepartments() {
  vector<Node*> tmp = this->getChildren();
  return reinterpret_cast<vector<DepartmentNode*>*>(&tmp);
}
常量向量*FacultyNode::getDepartments(){ 向量tmp=this->getChildren(); 返回重新解释(tmp); } 正如詹姆斯·麦克内利斯(James McNellis)在下面的评论中指出的那样,以下内容是不安全的(他更为直截了当)。我自己也不会使用它,即使我不知道为什么它会触发未定义的行为——也许我应该这样做


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

const vector<DepartmentNode*>* FacultyNode::getDepartments() {
  vector<Node*> tmp = this->getChildren();
  return reinterpret_cast<vector<DepartmentNode*>*>(&tmp);
}
常量向量*FacultyNode::getDepartments(){ 向量tmp=this->getChildren(); 返回重新解释(tmp); }
您真的需要复制向量吗?如果不必这样做,您可以编写一个迭代器,当用户请求项时,即在运算符*上,该迭代器将强制转换

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.
  // ...
};
MyIterator FacultyNode::getDepartmentsBegin(){ vector&tmp=this->getChildren(); 返回MyIterator(tmp.begin()); } MyIterator FacultyNode::getDepartmentsEnd(){ vector&tmp=this->getChildren(); 返回MyIterator(tmp.end()); } 结构MyIterator{ 向量::迭代器m_it; MyIterator(vector it):m_it(it){} 部门*操作员*(){返回(部门*)*it;} void运算符++(){m_it++;} //以同样的方式,转发给m_it,实现其他需要的迭代器。 // ... };
希望它能澄清我的意思。

你真的需要复制向量吗?如果不必这样做,您可以编写一个迭代器,当用户请求项时,即在运算符*上,该迭代器将强制转换

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.
  // ...
};
MyIterator FacultyNode::getDepartmentsBegin(){ vector&tmp=this->getChildren(); 返回MyIterator(tmp.begin()); } MyIterator FacultyNode::getDepartmentsEnd(){ vector&tmp=this->getChildren(); 返回MyIterator(tmp.end()); } 结构MyIterator{ 向量::迭代器m_it; MyIterator(vector it):m_it(it){} 部门*操作员*(){返回(部门*)*it;} void运算符++(){m_it++;} //以同样的方式,转发给m_it,实现其他需要的迭代器。 // ... };
希望它能澄清我的意思。

也许你可以把
节点
变成一个模板

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>;
模板
类节点{
vector childs;//我认为Boost.ptr容器会更好
//简单的节点操作方法
常量向量&getChildren(){return childs;}
}
类FacultyNode:公共节点;

也许您可以将
节点
转换为模板

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>;
模板
类节点{
vector childs;//我认为Boost.ptr容器会更好
//简单的节点操作方法
常量向量&getChildren(){return childs;}
}
类FacultyNode:公共节点;

这不是未定义的行为吗?你不能这样重新解释
向量。为什么?指向
节点
的指针的大小与指向
部门节点
的指针的大小相同,因此,如果他确定他的向量实际上只包含
部门节点
s,那么就可以了。@James:是的,对不起,我没有意识到他是按值返回的。但是如果他返回一个指针,那就没问题了。@Daniel:不管你是按值还是按指针返回,你不能像使用
向量那样使用
向量。它们在内存中可能有不同的表示,编译器可能会对它们进行不同的优化,或者如果您尝试这样做,编译器可能会插入运行时检查来断言。唯一可以使用
向量的类型是
向量
(或者该类型的任何const/volatile限定版本,或者作为
字符数组
,尽管这不是一件特别有用的事情。)。这不是未定义的行为吗?你不能
以这种方式重新解释
向量
。为什么?指向
节点
的指针的大小与指向
部门节点
的指针的大小相同,因此,如果他确定他的向量实际上只包含
部门节点
s,那么就可以了。@James:是的,对不起,我没有意识到他是按值返回的。但是如果他返回一个指针,那就没问题了。@Daniel:不管你是按值还是按指针返回,你不能像使用
向量那样使用
向量。它们在内存中可能有不同的表示,编译器可能会对它们进行不同的优化,或者如果您尝试这样做,编译器可能会插入运行时检查来断言。唯一可以使用
向量
的类型是
向量
(或者该类型的任何const/volatile限定版本,或者作为
char
的数组,尽管这不是一件特别有用的事情。)。我认为自定义迭代器是这里最好的方法。这会很有趣。对不起,我不是很精通迭代器。我该怎么做呢?我认为自定义迭代器是这里最好的方法。这会很有趣。对不起,我不是很精通迭代器。我该怎么做?这是我