我有一个基类和一个子类:
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 > 的适当转换
那么如何将子类向量传递给需要基类向量的函数呢?
vector<Base>并分别vector<Sub>保存实际Base和Sub对象。它们是不同的向量类型,并且它们的数据数组也不同,因此您不能只在需要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)