如何从基类容器中提取派生类?

时间:2010-12-02 18:13:08

标签: c++ templates class casting

使用公共父类将不同类型的对象存储在同一容器中之后,我需要将它们提取出来。

[测试/ 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树中节点的泛型类型。我认识到我采用的设计可能不是最合适的!所以我愿意接受建议!

我会感谢任何帮助!

5 个答案:

答案 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