C++ 传递派生类型的std::vector,其中需要基类型的std::vector

C++ 传递派生类型的std::vector,其中需要基类型的std::vector,c++,polymorphism,C++,Polymorphism,我有一个基本类: class Member { .... } 和一个派生类,如下所示: class Mine_sweeper : private Member { .... } 然后我有一个容器: class Population { public: std::vector<Member>& m_members; Population(std::vector<Member>& members); } 类人口 { 公众:

我有一个基本类:

class Member
{
    ....
}
和一个派生类,如下所示:

class Mine_sweeper : private Member
{
    ....
}
然后我有一个容器:

class Population
{
public:
    std::vector<Member>& m_members;
    Population(std::vector<Member>& members);
}
类人口
{
公众:
std::向量&m_成员;
人口(性病:病媒和成员);
}
当我将人口构造函数与成员向量一起使用时,它编译为OK。但若我试图将人口的m_成员与扫雷者向量联系起来,编译器就会抛出一个错误

std::vector<Member> members;
Population pop(members); // this compiles OK

std::vector<Mine_sweeper> sweepers;
Population pop(sweepers); // but here I get an error
std::向量成员;
人口(成员);//这个编译没问题
std::矢量扫掠器;
人口流行(清扫者);//但这里我得到一个错误

main.cpp(23):错误C2664:'Population::Population(std::vector&'):无法将参数1从'std::vector'转换为'std::vector&'Population类的构造函数将参数转换为包含成员类数组的向量。您可以将派生类传递给以基类为参数的对象,或者从派生类向上转换为基类,这是正确的,但是您在这里所做的是不同的。您并没有将派生类发送给使用基类参数的函数,而是发送了一个完全不同的不相关类型,您将std::vector发送给需要std::vector的对象

当您在编译时创建std::vector时,它将创建一个vector类,其中包含所有特定于它如何遍历int等的详细信息。这是一个数组或“int”。将其传递给接受一个双精度数组的函数有意义吗?然后该函数正在处理double,例如,要移动到下一个double,它可能会向前移动8个字节,而不是4个字节,这样做是错误的

您必须手动创建两个版本的Population类,或者使用模板来实现。编辑:见YSC的答案,他为构造函数模板


或者,您可能需要一个向量/数组,它可以同时包含类、基和扫雷器两种类型。为此,不能将对象本身存储在数组中,因为这两种类型的对象可能大小不同,成员也不同。所以你可以有一个指向基类的指针向量。然后,多态性部分用于在取消引用其中一个指针时识别是指向基地还是扫雷舰。虚拟函数用于根据所属对象调用正确的函数

你不能。不是现在这样。这是因为
std::vector
不是从
std::vector
派生的,不管
B
是从
A
派生的

但是等等。。。让我们用一个简单的例子来简化您的问题:

struct A {};
struct B : A {};
void f(std::vector<A> const&) {}

int main()
{
    std::vector<A> vecA;
    std::vector<B> vecB;
    f(vecA);
    f(vecB); // error
}
解决方案是使用从
B
A
的现有隐式转换提供显式转换:

struct A {};
struct B : A {};
class Container
{
    std::vector<A*> _items;
public:
    template<class T>
    Container(std::vector<T> v)
        : _items(v.begin(), v.end())
    {}
    // other stuff, see rule of 5
};


int main()
{
    std::vector<A*> vecA;
    std::vector<B*> vecB;

    Container contA(vecA);
    Container contB(vecB);
}
struct A{};
结构B:A{};
类容器
{
标准::向量_项;
公众:
模板
容器(标准::向量v)
:_项(v.begin(),v.end())
{}
//其他内容,参见第5条规则
};
int main()
{
向量向量向量机;
std::vecB;
集装箱集装箱集装箱(vecA);
集装箱集装箱(vecB);
}

一旦你有了一个基本的工作转换,你需要弄清楚如何使用
std::unique_ptr
std::shared_ptr
std::weak_ptr

扫雷者的向量不是成员的“种类”向量,即使扫雷者是“种类”成员。您不能使用
向量
代替
向量

使用
vector
代替
vector
vector
。这使您能够拥有异构的成员群体(即扫雷者和其他成员子类型)

或者,将填充类转换为类模板:

class Population<T>
{
public:
    std::vector<T>& m_members;
    Population(std::vector<T>& members);
}
template <typename T>
void foo(const vector<T>& v) {
    v[0].bar(); // do something with v
}
类人口
{
公众:
std::向量&m_成员;
人口(性病:病媒和成员);
}

这样,一个填充实例可能只包含一种类型的成员。

您不能只将派生类对象的向量传递给需要基类对象向量的函数,因为向量不是从向量派生的

你可以做一些转换,得到一个向量切片,如下所示:

class Mine_sweeper : private Member
{
    ....
}
向量转换(base_vec.begin(),base_vec.end())

但这并不高效,如果调用方法在您的控制下,您可以只使用模板:

class Population<T>
{
public:
    std::vector<T>& m_members;
    Population(std::vector<T>& members);
}
template <typename T>
void foo(const vector<T>& v) {
    v[0].bar(); // do something with v
}

您也可以将
std::transform
std::back\u inserter
一起使用,请参见[

@A.Matric“将人口类转换为类模板”。这就是我所说的,但YSC的答案更好。
#include <vector>

class Base{
public:
    void bar() const {}
};

class Derived: public Base{
};

template<typename T, typename Enable=std::enable_if<std::is_base_of<T, Base>::value>>
void foo(const std::vector<T>& v) {
    v[0].bar();
}

int main() {
    std::vector<Derived> a(1);
    foo(a);
}