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;iO(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
的数组,尽管这不是一件特别有用的事情。)。我认为自定义迭代器是这里最好的方法。这会很有趣。对不起,我不是很精通迭代器。我该怎么做呢?我认为自定义迭代器是这里最好的方法。这会很有趣。对不起,我不是很精通迭代器。我该怎么做?这是我