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
派生的,不管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);
}