如何多态地使用数组或指针向量?

How to use arrays or vectors of pointers polymorphically?

我在许多不同的帖子中都读过关于这个问题的内容,数组不能被多态处理,应该使用指针数组来代替,我很清楚其背后的原因。

但是,我找不到它是如何完成的示例,而且我似乎无法让它工作。考虑以下代码:

#include <vector>

class Base
{
    public:
        Base();
        virtual ~Base();
};

class Derived : Base
{
    public:
        Derived();
        ~Derived();
};

void foo( std::vector<Base*> )
{
    // do something
}

int main()
{
    std::vector<Derived*> bar;
    foo(bar);

    return 0;
}

编译这个给出错误信息

could not convert 'bar' from 'std::vector<Derived*>' to 'std::vector<Base*>

我是不是遗漏了什么或者设计是否存在根本性缺陷?提前致谢。

std::vector<Derived*>std::vector<Base*>是不同的类型,它们之间没有转换。不过看来你需要的是

std::vector<Base*> bar;
foo(bar);

即让多态性在向量的元素级别工作。

但是,请注意,为了在通常意义上使用多态性,Derived 必须 publiclyBase:

继承
class Derived : public Base
                ^^^^^^

struct Derived : Base

Am I missing something or is the design even fundamentally flawed?

无法将 std::vector<Derived*> 的对象自动转换为 std::vector<Base*>。他们是两种完全不同的类型。

我可以想到以下选项来解决这个问题:

  1. 更改 foo 以接受 std::vector<Derived*>

    void foo( std::vector<Derived*> )
    {
        // do something
    }
    
  2. foo更改为函数模板。

    template <typename T>
    void foo( std::vector<T*> )
    {
        // do something with the implicit understanding that
        // T is derived from Base.
    }
    
  3. 更改调用代码以使用std::vector<Base*>

要完成 juanchopanza 的回答,您可以这样使用 std::vector<Derived*>:

void itemfoo(Base* item)
{
    // do something
}

template<typename Iter>
void foo(Iter begin, Iter end) {
    // do stuff per element
    while(begin != end)
        itemfoo(*begin++);
}

int main()
{
    std::vector<Derived*> bar;
    foo(bar.begin(), bar.end());

    return 0;
}

如果你需要对整个范围做一个操作,并且按照Base*来做,那么你可以这样做:

void foo(Base** begin, Base** end) {
     // do stuff on range [begin, end)
}

int main()
{
    std::vector<Derived*> bar;
    if(bar.empty())
        foo(nullptr, nullptr); // or however you handle the empty range
    else
        foo(&bar[0], &bar[0] + bar.size());

    return 0;
}