C ++:如何将派生类的容器传递给期望其基类容器的函数?

时间:2010-03-04 01:36:12

标签: c++ stl polymorphism containers

HI!任何人都知道如何在下面的代码中使用“chug(derlist);”行吗?

#include <iostream>
#include <list>
using namespace std;

class Base
{
public:
    virtual void chug() { cout << "Base chug\n"; }
};

class Derived : public Base
{
public:
    virtual void chug() { cout << "Derived chug\n"; }
    void foo() { cout << "Derived foo\n"; }
};

void chug(list<Base*>& alist)
{
    for (list<Base*>::iterator i = alist.begin(), z = alist.end(); i != z; ++i)
        (*i)->chug();
}

int main() 
{
    list<Base*> baselist;
    list<Derived*> derlist;

    baselist.push_back(new Base);
    baselist.push_back(new Base);
    derlist.push_back(new Derived);
    derlist.push_back(new Derived);

    chug(baselist);
    // chug(derlist);  // How do I make this work?

    return 0;
}

我需要这个的原因基本上是,我有一个非常复杂的对象的容器,我需要传递给某些只涉及这些复杂对象中的一个或两个虚函数的函数。

我知道简短的回答是“你不能”,我真的在寻找人们用来解决这个问题的任何技巧/习语。

提前致谢。

4 个答案:

答案 0 :(得分:5)

你的问题很奇怪;该主题询问“我如何将物品放入容器中而不会失去多态性” - 但这是在乞求这个问题;容器中的项目不会丢失多态性。你只有一个基本类型的容器,一切正常。

从你的示例中,它看起来你问的是“如何将子指针容器转换为基指针容器?” - 答案就是,你做不到。子指针可以转换为基指针,子指针的容器不是。它们是不相关的类型。虽然,请注意,shared_ptr 可以转换为shared_ptr,但这只是因为它们具有额外的魔力才能使其发挥作用。容器没有这样的魔力。

一个答案是使chug成为模板函数(免责声明:我不在带编译器的计算机上,所以我没有尝试编译它):

template<typename C, typename T>
void chug(const C<T>& container)
{
    typedef typename C<T>::iterator iter;
    for(iter i = container.begin(); i < container.end(); ++i)
    {
        (*i)->chug();
    }
}

然后chug可以接受任何类型的任何容器,只要它是一个指针容器并且有一个突突方法。

答案 1 :(得分:1)

通过指针存储它们(boost :: shared_ptr是一个流行的选项),或者使用在内部存储指针的Boost ptr_containers,但在外部提供一个很好的API(当然还有完全自动删除)。

#include <boost/ptr_container/ptr_vector.hpp>

boost::ptr_vector<FooBase> foos;
foos.push_back(new FooDerived(...));
foos[0].memberFunc();

容器的多态转换根本不可能,因此总是传递ptr_vector&lt; Base&gt;&amp;并且在功能本身中贬低。

答案 2 :(得分:0)

也许你可以使chug模板函数将模板参数转换为Base*类型,然后在其上调用chug

答案 3 :(得分:0)

为什么不使chug成为基于模板的函数,以便它可以有基类和派生类型的实例?

或者,为了获得更好的解决方案,您可以使用std::for_each