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

0 c++ stdvector

我有一个类和一个类:

class Base{
  public:
    Base(){}
    // ...
};

class Sub: public Base{
    int param;
  public:
    Sub(){}
    // ...
};
Run Code Online (Sandbox Code Playgroud)

我还有一个需要Base向量的函数,如下所示:

void doSomeThing(vector<Base> vectorOfBases){
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我需要这样调用该函数:

vector<Sub> myVectorOfSubs;
doSomeThing(myVectorOfSubs);
Run Code Online (Sandbox Code Playgroud)

编译器告诉我:

没有从向量 < Sub > 到向量 < Base > 的适当转换

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

Rem*_*eau 5

vector<Base>并分别vector<Sub>保存实际BaseSub对象。它们是不同的向量类型,并且它们的数据数组也不同,因此您不能只在需要vector<Sub>a 的地方传递 a 。vector<Base>如果尝试构造一个vector<Base>usingSub对象,就会发生切片

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

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

    void doSomeThing(std::vector<Base*> &vectorOfBasePtrs) {
        for (Base *b : vectorOfBasePtrs) {
            // ...
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    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);
    
    Run Code Online (Sandbox Code Playgroud)
  • 更改函数以采用vector<T>whereT是 模板参数(理想情况下通过std::enable_ifand使用 SFINAEstd::is_base_of以确保它T实际上是Base或从 派生的类型Base):

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

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

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

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

    std::vector<Sub> myVectorOfSubs;
    ...
    
    doSomeThing(myVectorOfSubs.begin(), myVectorOfSubs.end());
    
    Run Code Online (Sandbox Code Playgroud)