如何将 subclass 的向量传递给需要 base class 向量的函数
How can I pass a vector of subclass to a function that requires a vector of base class
我有一个 Base class 和一个 Sub class:
class Base{
public:
Base(){}
// ...
};
class Sub: public Base{
int param;
public:
Sub(){}
// ...
};
我还有一个函数需要 Base 的 vector,如下所示:
void doSomeThing(vector<Base> vectorOfBases){
// ...
}
我需要这样调用函数:
vector<Sub> myVectorOfSubs;
doSomeThing(myVectorOfSubs);
编译器告诉我:
there is no appropriate conversion from vector< Sub > to vector< Base >
那么如何将 Sub class 的向量传递给需要 Base class 向量的函数?
So how can I pass a vector of Sub class to a function that requires a vector of Base class?
你不能。
std::vector<Base>
和 std::vector<Sub>
之间没有超类-子类关系。
这是绕过该限制的一种方法。更改函数以使用可以与包含 Base
或 Sub
对象的任何容器一起使用的函数模板。
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
}
}
vector<Base>
和 vector<Sub>
分别保存实际的 Base
和 Sub
对象。它们是不同的矢量类型,它们的数据数组也不同,所以你不能只传递一个 vector<Sub>
而应该是 vector<Base>
。如果尝试使用 Sub
个对象构建 vector<Base>
,slicing will occur.
要使代码正常工作,您可以:
将函数改为采用 vector<Base*>
,然后您可以构造一个 vector<Base*>
,其元素指向您的 vector<Sub>
元素,例如:
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_if
and std::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());
我有一个 Base class 和一个 Sub class:
class Base{
public:
Base(){}
// ...
};
class Sub: public Base{
int param;
public:
Sub(){}
// ...
};
我还有一个函数需要 Base 的 vector,如下所示:
void doSomeThing(vector<Base> vectorOfBases){
// ...
}
我需要这样调用函数:
vector<Sub> myVectorOfSubs;
doSomeThing(myVectorOfSubs);
编译器告诉我:
there is no appropriate conversion from vector< Sub > to vector< Base >
那么如何将 Sub class 的向量传递给需要 Base class 向量的函数?
So how can I pass a vector of Sub class to a function that requires a vector of Base class?
你不能。
std::vector<Base>
和 std::vector<Sub>
之间没有超类-子类关系。
这是绕过该限制的一种方法。更改函数以使用可以与包含 Base
或 Sub
对象的任何容器一起使用的函数模板。
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
}
}
vector<Base>
和 vector<Sub>
分别保存实际的 Base
和 Sub
对象。它们是不同的矢量类型,它们的数据数组也不同,所以你不能只传递一个 vector<Sub>
而应该是 vector<Base>
。如果尝试使用 Sub
个对象构建 vector<Base>
,slicing will occur.
要使代码正常工作,您可以:
将函数改为采用
vector<Base*>
,然后您可以构造一个vector<Base*>
,其元素指向您的vector<Sub>
元素,例如: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_if
andstd::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());