如何将子类向量传递给需要基类向量的函数

How can I pass a vector of subclass to a function that requires a vector of base class

本文关键字:向量 基类 函数 子类      更新时间:2023-10-16

我有一个类和一个类:

class Base{
public:
Base(){}
// ...
};
class Sub: public Base{
int param;
public:
Sub(){}
// ...
};

而且我还有一个函数需要像这样的Base向量

void doSomeThing(vector<Base> vectorOfBases){
// ...
}

我需要像这样调用函数:

vector<Sub> myVectorOfSubs;
doSomeThing(myVectorOfSubs);

编译器告诉我:

没有从矢量<子>到矢量的适当转换<基本>

那么如何将 Sub 类的向量传递给需要基类向量的函数呢?

vector<Base>vector<Sub>分别保存实际的BaseSub对象。 它们是不同的向量类型,并且它们的数据数组不同,因此您不能只传递预期vector<Base>vector<Sub>。 如果尝试使用Sub对象构建vector<Base>,则会发生切片。

要使代码正常工作,您可以:

  • 将函数更改为采用vector<Base*>,然后您可以构造一个元素指向vector<Sub>元素的vector<Base*>,例如:

    void doSomeThing(std::vector<Base*> &vectorOfBasePtrs) {
    for (Base *b : vectorOfBasePtrs) {
    // ...
    }
    }
    

    std::vector<Sub> myVectorOfSubs;
    ...
    std::vector<Base*> myVectorOfBasePtrs;
    myVectorOfBasePtrs.resize(myVectorOfSubs.size());
    std::transform(myVectorOfSubs.begin(), myVectorOfSubs.end(), myVectorOfBasePtrs.begin(),
    [](Sub &s){ return static_cast<Base*>(&s); }
    );
    /* or:
    myVectorOfBasePtrs.reserve(myVectorOfSubs.size());
    for (Sub &s : myVectorOfSubs) {
    myVectorOfBasePtrs.push_back(&s);
    }
    */
    doSomeThing(myVectorOfBasePtrs);
    
  • 更改函数以采用vector<T>,其中T是模板参数(理想情况下,通过std::enable_ifstd::is_base_of使用 SFINAE 以确保T实际上是Base或从Base派生的类型):

    template<typename T>
    void doSomeThing(std::vector<T> &vectorOfObjs) {
    for (Base &b : vectorOfObjs) {
    // ...
    }
    }
    

    std::vector<Sub> myVectorOfSubs;
    ...
    doSomeThing(myVectorOfSubs);
    
  • 更改函数以采用实际容器的模板化T,而不是容器元素类型:

    template<typename Container>
    void doSomeThing(Container &containerOfObjs) {
    for (Base &b : containerOfObjs) {
    // ...
    }
    }
    
  • 将函数更改为采用一对迭代器而不是容器本身,然后您可以从vector<Sub>传入迭代器:

    template <typename Iterator>
    void doSomeThing(Iterator begin, Iterator end) {
    while (begin != end) {
    Base &b = *begin;
    // ...
    ++begin;
    }
    }
    

    std::vector<Sub> myVectorOfSubs;
    ...
    doSomeThing(myVectorOfSubs.begin(), myVectorOfSubs.end());
    

那么如何将 Sub 类的向量传递给需要基类向量的函数呢?

你不能。

std::vector<Base>std::vector<Sub>之间没有超类-子关系。

这是绕过该限制的一种方法。 将函数更改为使用可处理包含BaseSub对象的任何容器的函数模板。

template <typename Container>
void doSomeThing(Container& container)
{
// Do something for each item of the container assuming that
// the container contains objects of type Base or any of its derived classes.
for ( Base& baseRef : container )
{
// Use baseRef
}
}