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

How to use arrays or vectors of pointers polymorphically?

本文关键字:指针 数组 向量 何多态 多态      更新时间:2023-10-16

我在许多不同的帖子中读到过关于这个问题的文章,数组不应该多态处理,应该使用指针数组代替,它背后的原因对我来说很清楚。

但是,我

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

#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必须Base公开继承:

class Derived : public Base
                ^^^^^^

struct Derived : 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;
}

我是否错过了什么,或者设计甚至存在根本性的缺陷?

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*>