使用公共父类将不同类型的对象存储在同一容器中之后,我需要将它们提取出来。
[测试/ test0.c ++] :
int main()
{
element wrapper;
wrapper.name = "div";
wrapper.attributes["id"] = "wrapper";
cargo<string> text("Learn from yesterday, live for today, hope for tomorrow.");
wrapper.children.push_back(&text);
cout << "Name:\t" << wrapper.name << endl;
/* I have an explicit cast here,
* but it can't be used this way
* since children may have different types
*/
cout << "Cargo:\t" << ((cargo< string >*) wrapper.children[0])->value << endl;
return 0;
}
[出处/ element.h展开]
struct element
{
std::string name;
std::map< std::string, std::string > attributes;
std::vector< node* > children;
};
[出处/ node.h]
struct node
{ };
[出处/ cargo.h]
template <typename Type>
struct cargo
: public node
{
Type value;
cargo(Type value)
: value(value)
{ }
};
我需要将某种类型的持有者与真实节点类型相关联,并在更远的投射提取操作中使用它...而不是在我的测试中使用那种硬编码的。
更新
我要做的是一个简单的文档对象模型数据结构,将其用作类似xml的语言解析器的符号表条目。我不想使用任何现有的XML库,因为它们非常大。我认为DOM的想法很简单,所以我可以轻松地将它用于一些更复杂的操作,例如,通过使用cargo<Type>
允许DOM树中节点的泛型类型。我认识到我采用的设计可能不是最合适的!所以我愿意接受建议!
我会感谢任何帮助!
答案 0 :(得分:1)
如果您只是流式传输,则可以在基类中实现流运算符,然后委托派生类中的方法,否则查看访问者模式。如果没有真正掌握你可能会在cargo
上做什么样的操作,就很难做出进一步的建议......
答案 1 :(得分:1)
如果您不打算在检索时多态地处理容器成员,Boost.Variant可能有助于以确定的方式包装容器成员。
变体类模板是安全的, 通用的,基于堆栈的区分 联合容器,提供简单 操纵对象的解决方案 来自一组异类的 统一的方式。而标准 容器如std :: vector可能是 被认为是“多价值,单一的 类型,“变体是”多种类型,单一 值“。
this prior question中有一些示例代码。
答案 2 :(得分:1)
这个问题可能更多的是关于设计而不是实施
虽然Boost.Variant和Boost.Any会起作用,但它们只是一种解决方法。真正的问题可能是,从节点类派生的类的责任的可变部分未被封装
您可以尝试使用合成。一个主机类用于通用接口和适当数量的组件/代理/任何(那些将来自解决方案设计:))。
或者......完全不同的解决方案可能适合您。您可能想冒险使用元编程单词并抛弃公共接口。相反,像元组(类型列表)这样的实体可能会有所帮助。
最诚挚的问候,
马尔钦
答案 3 :(得分:0)
如果没有演员,你就不会有这样的事情。
但最重要的是,这通常意味着你走错了路。只要您确定cargo
将从node
公开继承,您就会在这两个类之间提供非常强大的关系,并且“成为node
”具有比以下更强的含义:
我可以插入容器中 以及其他
node
派生类型
我们需要知道什么是node
以及可以用它来做些什么来帮助你。但是,如果您真的需要坚持使用初始解决方案,boost.variant可以帮助您。
答案 4 :(得分:0)
您应该设计代码并不关心基类类型。提供一个对所有人都相同的界面。或者将您需要的纯虚方法添加到基类并在派生类中实现。
假设有些不可能,你尝试过dynamic_cast吗?如果转换失败,则返回null,而不是像上面的static_cast那样抛出。
希望这有帮助, Beezler