遍历复合结构中的对象 (C++)

问题描述 投票:0回答:1

在我当前的项目中,我声明了一个 BaseComponent 类以及从它派生的许多类,这些类被构造为基于复合设计模式的对象树。 BaseComponent包含许多虚拟成员函数。在父类中,这些成员函数通过子对象列表进行交互,在每个对象中递归调用各自的方法。子类根据其目的实现虚函数。

#include <vector>

class BaseComponent
{
  public:
  virtual void Method(){}
};

class ParentComponent : public BaseComponent
{
  private:
  std::vector<BaseComponent*> list;
  
  public:
  void Method()
  {
    for (int count=0;count<list.size();count++)
    {
      list[count]->Method();
    }
  }
};

class ChildComponent : public BaseComponent
{
  public:
  void Method()
  {
    //do something
  }
};

问题是,对于我声明的每个虚拟成员函数(它们很多),我必须在父类中编写迭代。此外,可能会有许多不同类型的父类。我的代码显然不能像现在这样可持续。

我考虑使用一些(内部或外部)迭代器模式来避免重复代码的扩散。但是,我真的不想在堆上分配无数的迭代器对象,我想将它们保留在堆栈上。关于如何改进我的代码有什么想法吗?

c++ oop design-patterns iterator composite
1个回答
0
投票

迭代可以以相对简单的方式抽象出来。

class ParentComponent : public BaseComponent
{
  private:
  std::vector<BaseComponent*> list;
  
  public:
  template <void (BaseCompoment::*PMF)()>
  void Run()
  {
    for (int count=0;count<list.size();count++)
    {
      (list[count]->*PMF)();
    }
  }

  // Can be deduplicated but only with a macro 
  void Method1() override { Run<&BaseComponent::Method1>(); }
  void Method2() override { Run<&BaseComponent::Method2>(); }
};

但是如果不同的方法有不同的参数怎么办?这也可以做到。

  template <auto PMF, typename ... Arg>
  void Run(Arg&& ... arg)
  {
    for (int count=0;count<list.size();count++)
    {
      (list[count]->*PMF)(std::forward<Arg>(arg)...);
    }
  }

  void Method1(     ) override { Run<&BaseComponent::Method1>( ); }
  void Method2(int x) override { Run<&BaseComponent::Method2>(x); }

您也不需要使用 PMF,任何类型的可调用都可以使用。

  template <auto func, typename ... Arg>
  void Run(Arg&& ... arg)
  {
    for (int count=0;count<list.size();count++)
    {
      std::invoke(func, list[count], std::forward<Arg>(arg)...);
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.