如果子class 派生自基class,如何自动调用方法或生成代码?

How to automatically call a method or generate code if a subclass derived from a base class?

我有一些描述能力/行为的 classes,例如飞行或驾驶等。这些 classes 中的每一个都有一个必须调用的特定方法来加载一些数据 -例如,Flyable 有 loadFlyData(),Drivable 有 loadDriveData()。对于每个 class,方法名称都是唯一的。

我有许多派生的 classes,它们可能继承自这些行为中的一个或多个 classes。每个派生的 classes 都有一个方法叫做 loadData(),我们应该在其中调用所有父行为 classes 的方法,例如 loadFlyData()loadDriveData() 等....有没有办法使用元编程自动生成这个方法?由于有许多派生的 classes,如果我可以使用元编程生成这些方法,它可能更易于维护...

行为 classes : (一个对象 class 可能有任何这些行为,并且必须调用 classes "load" 方法...

class Flyable {
  void loadFlyData() {
  }
};

class Drivable{
  void loadDriveData() {
  }
};

所有对象 class 派生自对象:

class Object {
  virtual void loadData() {
  }
};

派生class:

class FlyingCar : public Object, public Flyable, public Drivable {
    virtual void loadData() override {
        // How to automatically generate code so that the next two lines are called:
        loadFlyData();
        loadDriveData();
  }
};

当然可以。但是,您需要采用一些约定,以便代码可以通用。 See it live.

#include <iostream>
using namespace std;

struct Flyable{
  int loadConcreteData(){
    cout << "Flyable\n"; return 0;
  }
};

struct Drivable{
  int loadConcreteData(){
     cout << "Drivable\n"; return 0;
  }
};

class Object{
  virtual void loadData(){
  }
};

template<class ...CS>
struct ConcreteLoader : Object, CS... {
    void loadData() override {
        int load[] = {
            this->CS::loadConcreteData()...
        };
    }
};

class FlyingCar : public ConcreteLoader<Flyable,Drivable>{
};

int main() {
    FlyingCar fc;
    fc.loadData();
    return 0;
}

需要提及的更改:

  1. 必须更改每个具体 Load 函数的 return 类型。这是为了方便"array trick"扩展参数包。
  2. 所有加载函数的名称都是相同的,也是出于同样的原因。

一旦 c++17 和折叠表达式推出,原因 (1) 可能会过时。

你可以创建一个免费函数 loadXData() 如果你的 class 不是 X:

namespace detail
{

void loadFlyData(Flyable* ptr) { ptr->loadFlyData(); }
void loadFlyData(...) {}

void loadDriveData(Drivable* ptr) { ptr->loadDriveData(); }
void loadDriveData(...) {}

}

class FlyingCar : public Object, public Flyable, public Drivable{
public:
    virtual void loadData()override{
        //How to automatically generate code so that the next two lines are called:
        detail::loadFlyData(this);
        detail::loadDriveData(this);
    }
};

demo

尽管我认为使用通用名称 loadData 并为所有可变参数调用它 parents 可能更可取:

template<typename... Policies>
struct ComposedType : Object, Policies...
{
    virtual void loadData() override {
        int arr[] = {
            ((void)Policies::loadData(), 0)...
        };
        (void)arr;
    }
};

using FlyingCar = ComposedType<Drivable, Flyable>;

demo

上面的loadData可以在C++1z中简化:

virtual void loadData() override {
    ((void)Policies::loadData(), ...);
}

demo