Geo*_* P. 15 c++ polymorphism containers c++11
假设我有一个虚拟基类和一些派生的具体类:
class Base { ... }
class DerivedA : public Base { ... }
class DerivedB : public Base { ... }
class DerivedC : public Base { ... }
Run Code Online (Sandbox Code Playgroud)
在某些地方,我有每个派生类的对象向量:
std::vector<DerivedA> my_a;
std::vector<DerivedB> my_b;
std::vector<DerivedC> my_c;
Run Code Online (Sandbox Code Playgroud)
现在,我经常需要迭代所有三个向量中的所有元素并运用基类接口.我可以编写三个for循环,每个循环完全相同.但显然这远非最佳解决方案.
有没有一种聪明的方法将向量连接到具有基类指针/引用的公共容器中,这样我只需要迭代一次?或任何其他想法如何优雅地解决这个问题?
Vit*_*meo 16
在您目前的情况下,不需要多态性.您可以简单地使用可变参数模板 + 高阶函数来迭代向量.这是使用fold表达式的C++ 17解决方案:
template <typename F, typename... Vectors>
void for_all_vectors(F&& f, Vectors&&... vs)
{
(std::for_each(std::forward<Vectors>(vs).begin(),
std::forward<Vectors>(vs).end(),
f), ...);
}
Run Code Online (Sandbox Code Playgroud)
用法:
int main()
{
std::vector<A> my_a;
std::vector<B> my_b;
std::vector<C> my_c;
for_all_vectors([](const auto& x){ something(x); }, my_a, my_b, my_c);
}
Run Code Online (Sandbox Code Playgroud)
在C++ 11/14中,您可以将fold表达式替换为for_each_argument:
template <typename TF, typename... Ts>
void for_each_argument(TF&& f, Ts&&... xs)
{
return (void)std::initializer_list<int>{
(f(std::forward<Ts>(xs)), 0)...};
}
template <typename F, typename... Vectors>
void for_all_vectors(F&& f, Vectors&&... vs)
{
for_each_argument([&f](auto&& v)
{
std::for_each(v.begin(), v.end(), f);
}, std::forward<Vectors>(vs)...);
}
Run Code Online (Sandbox Code Playgroud)
我解释了这个片段背后的想法,并在2015年CppCon演讲中对其进行了扩展:" for_each_argument解释和扩展".
只需有一个指向基类的指针即可。您不能拥有基类型的向量并将派生类放入其中,因为它们可能不具有相同的大小、相同的功能等。
所以我要做的是创建一个向量或类型 base*,然后您可以连接派生类的指针。
可能看起来像这样:
vector<base*> v;
v.push_back(&derivedClassVariableA);
v.push_back(&derivedClassVariableB);
Run Code Online (Sandbox Code Playgroud)
然后,只要您要使用的函数在基类中是虚拟的并且在派生中定义,您就可以开始了