简体   繁体   English

C ++中具有继承关系的对象的向量

[英]vector of objects with inheritance in C++

class IFeature
{
public:
  virtual std::string string() = 0;
};

class Feature2D
{
public:
  virtual std::string string() { .... }
};

class Feature3D
{
public:
  virtual std::string string() { .... }
};

void print(std::vector<IFeature*> & v)
{
  for (size_t i=0; i<v.size(); i++)
    std::cout << v[i]->string() << std::endl;
}

void main()
{
  std::vector<Feature2D*> v2d;
  // push...
  print(v2d); // compile error 

  std::vector<Feature3D*> v3d;
  // push...
  print(v3d); // compile error 
}

Any suggestions on how I can obtain this print function? 关于如何获得此打印功能的任何建议? (maybe using another data structure different by std::vector) (也许使用另一个与std :: vector不同的数据结构)

Thanks 谢谢

Use a template. 使用模板。

template<typename T> void print(std::vector<T *> const & v) {
  for (size_t i=0; i<v.size(); i++)
    std::cout << v[i]->string() << std::endl;
}

Or, use a virtual print member function: 或者,使用虚拟打印成员函数:

class IFeature
{
public:
  virtual std::string string() = 0;
  virtual void print(std::ostream & Dest) const = 0;
};

void print(std::vector<IFeature *> const & v) {
  for (size_t i=0; i<v.size(); i++) {
    v[i]->print(cout);
    cout << endl;
  }
}

Optionally combine with an operator<< 可选与运算符<<

inline std::ostream & operator<<(std::ostream & Dest, IFeature const & v) {
  v.print(Dest);
  return Dest;

void print(std::vector<IFeature *> const & v) {
  for (size_t i=0; i<v.size(); i++)
    std::cout << *(v[i]) << std::endl;
}

Just make the vectors IFeature* -vectors. 只需使向量IFeature *-向量即可。 You can store pointers for inherited classes in them just fine. 您可以在它们中存储继承类的指针。

std::vector<IFeature*> v2d;
v2d.push_back(new Feature2D());
print(v2d);

No need to use templates. 无需使用模板。 Pointers to the superclass are the way to go when you need to access common virtual functions. 当您需要访问常见的虚拟函数时,指向超类的指针是必经之路。 This way you can also mix different subclasses inside the same vector: 这样,您还可以在同一向量中混合使用不同的子类:

std::vector<IFeature*> vMixed;
vMixed.push_back(new Feature2D());
vMixed.push_back(new Feature3D());
print(vMixed);

Of course, if you also need pointers for the inherited classes, things get a bit more tricky. 当然,如果您还需要继承类的指针,则事情会变得有些棘手。 One option is to store them elsewhere separately. 一种选择是将它们分别存储在其他位置。 You can also downcast, but that is not usually recommendable. 您也可以垂头丧气,但这通常不值得推荐。

You can make print itself into a template: 您可以将print本身制作成模板:

template<typename T>
void print(T const &v)
{
  for (size_t i=0; i<v.size(); i++)
    std::cout << v[i]->string() << std::endl;
}

Better yet, use iterators, then it'll work on most other standard containers as well: 更好的是,使用迭代器,然后它将在大多数其他标准容器上运行:

template<typename T>
void print(T const &v)
{
  for (T::const_iterator i = v.begin(); i != v.end(); ++i)
    std::cout << (*i)->string() << std::endl;
}

Even better (thanks Pedro), pass the iterators themselves: 更好的是(感谢Pedro),自己传递迭代器:

template<typename Iter>
void print(Iter begin, Iter end) {
  for (Iter i = begin; i != end; ++i)
    std::cout << (*i)->string() << std::endl;
}

For the sake of completeness, I'll add that you can reinterpret_cast the vectors, since all vector share the same binary code. 为了完整性,我将添加您可以重新解释向量,因为所有向量共享相同的二进制代码。

print(reinterpret_cast<std::vector<IFeature*>&>(v2d));

C++ doesn't have covariance for template parameters, but you can simulate it partly if you know what it does under the hood. C ++没有模板参数的协方差,但是如果您知道其幕后工作的话,可以部分模拟它。 I found reinterpret_cast to be also useful to convert vector<T*>& to vector<const T*>& for contravariance. 我发现reinterpret_cast对于将vector<T*>&转换为vector<const T*>&矛盾也很有用。

Granted, this is very ugly. 当然,这非常丑陋。

What you are looking for here is interface covariance, which (as far as I know) is not possible on C++ classes. 您在这里寻找的是接口协方差,据我所知,这在C ++类中是不可能的。 You need to make print also a Templated function (replace IFeature* with T*). 您还需要使打印成为模板功能(用T *替换IFeature *)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM