如果子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;
}
需要提及的更改:
- 必须更改每个具体
Load
函数的 return 类型。这是为了方便"array trick"扩展参数包。
- 所有加载函数的名称都是相同的,也是出于同样的原因。
一旦 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);
}
};
尽管我认为使用通用名称 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>;
上面的loadData
可以在C++1z中简化:
virtual void loadData() override {
((void)Policies::loadData(), ...);
}
我有一些描述能力/行为的 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;
}
需要提及的更改:
- 必须更改每个具体
Load
函数的 return 类型。这是为了方便"array trick"扩展参数包。 - 所有加载函数的名称都是相同的,也是出于同样的原因。
一旦 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);
}
};
尽管我认为使用通用名称 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>;
上面的loadData
可以在C++1z中简化:
virtual void loadData() override {
((void)Policies::loadData(), ...);
}