C++连接多态对象的容器

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)

wandbox上的实例


在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)

wandbox上的实例

我解释了这个片段背后的想法,并在2015年CppCon演讲中对其进行了扩展:" for_each_argument解释和扩展".

  • @AndyG:好的一点,我现在转发折叠表达式示例中的向量.关于`F &&`:它可以接受不可移动的临时*(例如lambda与广义捕获不可移动的东西)*而`F`则不能. (2认同)

Cha*_*d K 4

只需有一个指向基类的指针即可。您不能拥有基类型的向量并将派生类放入其中,因为它们可能不具有相同的大小、相同的功能等。

所以我要做的是创建一个向量或类型 base*,然后您可以连接派生类的指针。

可能看起来像这样:

vector<base*> v;
v.push_back(&derivedClassVariableA);
v.push_back(&derivedClassVariableB);
Run Code Online (Sandbox Code Playgroud)

然后,只要您要使用的函数在基类中是虚拟的并且在派生中定义,您就可以开始了