std :: vector和polymorphism

时间:2011-09-13 09:53:05

标签: c++ stdvector

#include <iostream>
#include <vector>

using namespace std;

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

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

void f(Base *){
  cout << "f(Base *)" << endl;
}

void f(vector<Base *>){
  cout << "f(vector<Base *>)" << endl;
}

int main(int argc, const char *argv[])
{
  Deriv *d = new Deriv;
  vector<Deriv *> v;
  v.push_back(d);

  f(d); // works
  //f(v); // does not compile
  return 0;
}

第一个f()有效,但第二个给出编译时错误:

  

f(vector<Deriv *>) not found.

我的问题:有没有办法让它工作:某种带向量的多态性?

4 个答案:

答案 0 :(得分:4)

您想要的属性称为协方差。答案是否定的,你不能这样做:向量不是协变的。

为什么不允许这样做的典型例子是这样的:

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

void f(vector<Base *>& v){
  v.push_back(new Deriv2); // oops, just pushed a Deriv2 into a vector of Deriv
}

如果您没有向向量添加元素,则只需传递一对输入迭代器即可。传递输出迭代器也不起作用。

template <typename InputIterator>
void f(InputIterator first, InputIterator last);

f(v.begin(), v.end());

答案 1 :(得分:3)

AFAIK不是您想要的方式(vector<Base*>是与vector<Deriv*>完全不同的类型。)

这是一种替代方法 - 这当然是一种通用算法

template <typename Iterator>
void f(Iterator begin, Iterator end)
{
  // now do stuff...
}

致电

f(v.begin(), v.end());

答案 2 :(得分:1)

你应该在主

中写这个
  Deriv *d = new Deriv;
  vector<Base *> v;  // Correction
  v.push_back(d);

您仍然可以将Derived个对象推入容器,f()可以正常工作。

模板解决方案也很好:

template <typename T>
void f(std::vector<T>);

答案 3 :(得分:1)

BaseDeriv是协变类型,但std::vector<Base*>std::vector<Deriv*>不是协变类型。

X是协变类型B的对象时,您可以将D派生的任何类型的对象B分配给X。这就是你的第一种情况。