在C++中循环访问类继承
Iterate over class inheritances in C++
假设我有一些类架构(类的数量在开发期间不断增加(,每个类继承自具有相同基本接口的N个类。创建将迭代继承的基函数(在基类或派生类中(的最佳方法是什么(如果可能(?
目标:避免开发人员的错误,并确保我们不会忘记从所有继承中调用所有基本函数,并使代码更清晰易读和理解。
请参阅编辑注释以了解更新的状态
简短示例:
class shared_base {
public:
virtual void func() = 0;
}
class base_1 : virtual public shared_base {
public:
void func() override {}
}
class base_2 : virtual public shared_base {
public:
void func() override {}
}
class target : virtual public base_1, virtual public base_2 {
public:
void func() override {
// Instead of:
base_1::func();
base_2::func();
// ... My func() implementation
/*
~~TODO~~
for_each(std::begin(inheritances), std::end(inheritances), [](auto& inheritance) -> void { inheritance::func(); })
~~TODO~~
*/
}
}
更具描述性和实际性的示例:
class base {
public:
virtual void func() = 0;
/*...Some interface (pure virtual) functions...*/
}
class base_core : virtual public base {
public:
void func() override {}
/*...Some base implementations for the rest...*/
protected:
template <typename FuncT>
virtual void iterate_over_base_core_inheritances(FuncT function_to_apply) {
/*~~TODO~~*/
}
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_1 : virtual public Decorator {
public:
void func() override {
// Will iterate (once) over Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
}
/*More functions implementations*/
}
template <class Decorator = base_core, typename = typename std::enable_if<std::is_base_of<base_core, Decorator>::value>::type>
class core_2 : virtual public core_1<>, virtual public Decorator {
public:
void func() override {
// Will iterate (twice) over core_1 and Decorator
/*iterate_over_base_core_inheritances([](core_base*) -> void {
// Implementation
});*/
// Instead of:
Decorator::func();
core_1::func();
//... Self func() implementation
}
/*More functions implementations*/
protected:
// If it's not possible doing it in the upper hierarchy level is it possible do it here?
template <typename FuncT>
void iterate_over_base_core_inheritances(FuncT function_to_apply) override {
/*~~TODO~~*/
}
}
需要了解的一些事项:
- 我正在开发Linux 64x平台(Ubuntu 16.04( - 如果答案很重要的话。
- 此代码背后的想法是创建一种易于扩展和理解的装饰器 DP,并且还将使开发人员能够使用基类的
protected
函数/属性。
在此提交中可以找到一个实际示例(供我实际使用(。
编辑:
多亏了@RaymondChen我得到了一个有效的解决方案,(到目前为止(只有一个小问题:每次我想使用以这种方式实现的类时,我都需要在其模板参数列表中指定core_base
类(之前 - 我使用默认类型参数(。我正在寻找解决此问题的方法。
当前解决方案:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
创建实例示例:当前:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
期望:std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
在此提交中可以找到一个实际示例(供我实际使用(。
多亏了@RaymondChen,我通过以下解决方案非常接近我的原始目标 [请参阅底部的更新部分]:
template <class ...Decorators>
class core_2 : virtual public Decorators... {
public:
static_assert((std::is_base_of<base_core, Decorators>::value && ...), "All decorators must inherit from base_core class.");
void func() override {
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
解释:
使用参数包,我们可以创建一个我们继承的类的"列表",使用折叠表达式 [c++17],我们可以在几行代码中实现它。
优点与我最初的想法相比:
- 对象创建行现在更加清晰和合乎逻辑:之前:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<core_3<>>>>();
之后:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
因为core_1和core_3是独立的,但core_2正在使用它们。 - 基/派生类中不需要新功能,它只是适合目标行(例如
is_equal
本文中未提及的函数(。
丢失的功能:
is_base_of
的模板验证(用static_assert
和fold expressions
解决(。- 在尚无法指定继承的情况下进行默认继承(仍在尝试解决(。
电流:std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
期望:std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();
更新
经过大量的研究和尝试,我想出了以下解决方案(也通过 C++20concepts
功能进行了改进(:
template <class T>
concept Decorator = std::is_base_of_v<base_core, T>;
class empty_inheritance {};
template<typename Base = base_core, typename ...Decorators>
struct base_if_not_exists {
static constexpr bool value = sizeof...(Decorators);
using type = typename std::conditional<value, empty_inheritance, Base>::type;
};
template <Decorator ...Decorators>
class core_2 : virtual public base_if_not_exists<base_core, Decorators...>::type, virtual public Decorators... {
public:
void func() override {
if constexpr (!base_if_not_exists<base_core, Decorators...>::value) {
base_core::func();
}
(Decorators::func(), ...);
//... Self func() implementation
}
/*More functions implementations*/
}
:)不会丢失任何功能
- 继承和友元函数,从基类访问受保护的成员
- 如何在复杂继承中访问静态成员变量
- 如何使用 C++ 中的继承函数访问派生类中的局部变量
- 为什么继承的结构成员在联合中无法访问?
- 在C++中循环访问类继承
- 在使用受保护和继承时无法访问在类中声明的私有成员
- 当键是虚拟继承中涉及的基类指针时,对 std::unordered_map 项的访问崩溃
- 如何在C++中访问 DirectWrite 继承的接口?
- C++继承,无法访问继承的元素
- C++ 不明确访问 - 虚拟继承
- C++继承从基类指针访问派生类中的非虚拟函数
- 多重继承和访问不明确的元素
- 继承:访问另一个类的私有和公共部分
- 为什么我无法使用受保护/私有继承访问派生实例中基类的受保护成员?
- C 继承访问受保护的数据成员
- 通过继承访问受保护的成员
- 带模板的继承(访问子类成员函数内父类的变量和对象)
- 从外部访问静态成员并通过继承 c++ 访问静态成员
- 为什么我无法通过继承访问此方法?
- 如何使用模板继承访问基类的成员