在树转换中结合模板和继承
Combining templates and inheritance in tree conversion
我有数据存储在c++树结构中,我从文件中读取。树是这样的:
class BaseNode {
std::vector<BaseNode*> children_;
...
};
class WhiteNode : public BaseNode { ... };
class BlackNode : public BaseNode { ... };
树构建完成后,我想将其转换为字符串。
为了使树代码与转换代码分开,我想使用模板,即实现类似的东西:
template <class T>
T WhiteNode::Convert() { ... };
然而,由于树节点被存储为BaseNode*
,我不知道如何访问这样的模板成员函数。由于模板成员函数不能被继承,我认为这是行不通的。
我确实想出了一个可行的解决方案:
class BaseConversion {
public:
virtual ~BaseConversion() {}
virtual void * FromBlack() = 0;
virtual void * FromWhite() = 0;
};
template <class T>
class Conversion : public BaseConversion {
public:
void * FromBlack();
void * FromWhite();
};
class BaseNode {
std::vector<BaseNode*> children_;
virtual void * Convert(BaseConversion * conversion) = 0;
public:
virtual ~BaseNode() {}
template <class T>
T Convert() {
return *static_cast<T*>(Convert(new Conversion<T>));
}
};
class WhiteNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromWhite();
}
};
class BlackNode : public BaseNode {
void * Convert(BaseConversion * conversion) {
return conversion->FromBlack();
}
};
和转换逻辑可以完全分开:
template <>
void * Conversion<std::string>::FromWhite() {
return new std::string("converting WHITE node to std::string ...");
}
template <>
void * Conversion<std::string>::FromBlack() {
return new std::string("converting BLACK node to std::string ...");
}
测试代码:
BaseNode * node = new BlackNode;
std::cout << node->Convert<std::string>() << std::endl;
node = new WhiteNode;
std::cout << node->Convert<std::string>() << std::endl;
返回预期结果:
converting BLACK node to std::string ...
converting WHITE node to std::string ...
虽然这个解决方案有效,但我相信它可以更容易地完成。我想到的任何其他更简单的解决方案都失败了,例如,由于类型擦除。
我将感谢任何帮助。谢谢!
类似于您的解决方案,但没有void*.
class NodeVisitor
{
virtual void VisitBlack(BlackNode* node);
virtual void VisitWhite(BlackNode* node);
};
class BaseNode {
std::vector<BaseNode*> children_;
...
virtual void visit(NodeVisitor* visitor) = 0;
};
class WhiteNode : public BaseNode {
virtual void visit(NodeVisitor* visitor) { visitor->visitWhite(this); }
};
class BlackNode : public BaseNode {
virtual void visit(NodeVisitor* visitor) { visitor->visitBlack(this); }
};
然后std::string convert(BaseNode* node)
{
class ConvertVisitor
: public NodeVisitor
{
ConvertVisitor(std::string* res)
: m_res(res)
{ }
virtual void VisitBlack(BlackNode* node)
{
*m_res = // convert black node to string;
}
virtual void VisitWhite(BlackNode* node)
{
*m_res = // convert white node to string;
}
std::string* m_res;
};
std::string res;
ConvertVisitor visitor(&res);
node->visit(&visitor);
return res;
}
相关文章:
- 继承函数的重载解析
- 多态性和功能结合
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 为什么在保护模式下继承升级不起作用
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 混合组合和继承的C++问题
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 公共与私人继承
- 如何创建从同一类继承的不同对象的向量
- 所有版本的 GCC 都与默认成员初始值设定项作斗争,该初始值设定项捕获了这一点,并结合了继承的构造函数
- 结构绑定:与公共数据成员(继承的基类)结合
- 将继承与静态函数结合使用
- 在树转换中结合模板和继承
- 将非虚拟接口和多级继承结合在一起
- 关于const与引用和虚继承的结合
- 结合模板和继承
- 是否可以将友谊与继承结合起来访问私有数据成员?