在 C++ 中迭代类继承 [英] Iterate over class inheritances in C++

查看:93
本文介绍了在 C++ 中迭代类继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类架构(类的数量在开发期间不断增加),每个类都继承自 N 个具有相同基本接口的类.创建将迭代继承的基函数(在基类或派生类中)的最佳方法(如果可能)是什么?

Assume I have a some classes architecture (the number of the classes is growing up during the development time), that each class inherit from N classes with the same basic interface. What is the best way (if possible) to create a base function (in the base class OR in the derived class) that will iterate over the inheritances?

目标:避免开发人员的错误,并确保我们不会忘记从所有继承中调用所有基本函数使代码更清晰易读.

Target: Avoid developers mistakes and make sure we won't forget to call all the base functions from all of the inheritances & make the code more clear to read and understandable.

请查看更新状态的编辑说明

简短示例:

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函数/属性.
  • I am working on Linux 64x platform (Ubuntu 16.04)- if it's matter for the answers.
  • The idea behind this code is to create kind of Decorator DP, which will be easy to extend and to understand, and also will enable the developers to use the protected functions/attributes of the base class.

实际示例(供我实际使用)可以在此提交.

A practical example (for my actual use) can be found in this commit.

感谢@RaymondChen 我得到了一个可行的解决方案,(到目前为止) 只有一个小问题:每次我想使用以这种方式实现的类时,我都需要在它的模板参数列表中指定 core_base 类(之前 - 我使用的是默认类型参数).我正在寻找解决此问题的方法.
目前的解决方案:

Thanks to @RaymondChen I got a working solution, with (so far) only one minor issue: Every time I want to use a class that implemented this way, I need to specify the core_base class in it's template arguments list (before- I was using the default type parameter). I am looking for a way to solve this issue.
The current solution:

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_ptrbase = std::make_shared, core_3>();
期望:
std::shared_ptrbase = std::make_shared, core_3<>>();

实际示例(供我实际使用)可以在 这次提交.

Creating an instance example:
Current:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
Desired:
std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();

A practical example (for my actual use) can be found in this commit.

推荐答案

感谢 @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] 我们可以在短短几行代码中实现它.

Explanation:

Using parameters pack we can create a "list" of classes we inherit from, and using folding expression [c++17] we can implement it in just few lines of code.

  • 对象创建线现在更加清晰和合乎逻辑:
    之前:
    std::shared_ptrbase = std::make_shared<core_2<core_1<core_3<>>>>();
    之后:
    std::shared_ptrbase = std::make_shared, core_3>();
    因为 core_1 &core_3 是独立的,但 core_2 同时使用它们.
  • 在基类/派生类中不需要新函数,它只是适合目标行(例如在这篇文章中没有提到的 is_equal 函数中).
  • The object creation line is more clear and logically now:
    Before:
    std::shared_ptr<base> base = std::make_shared<core_2<core_1<core_3<>>>>();
    After:
    std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
    Because core_1 & core_3 are independent, but core_2 is using both of them.
  • No need of new function in the base/derived class, it's just fit within the target line (for example in is_equal function that didn't mention within this post).
  • is_base_of 的模板验证(使用 static_assert折叠表达式 解决).
  • 默认继承,以防未指定继承是不可能的(仍在尝试解决).
    当前:
    std::shared_ptrbase = std::make_shared, core_3>();
    期望:
    std::shared_ptrbase = std::make_shared, core_3<>>();
  • Template validation of is_base_of (Solved with static_assert & fold expressions).
  • Default inheritance in case that no inheritance specified is not possible yet (Still trying to solve).
    Current:
    std::shared_ptr<base> base = std::make_shared<core_2<core_1<base_core>, core_3<base_core>>>();
    Desired:
    std::shared_ptr<base> base = std::make_shared<core_2<core_1<>, core_3<>>>();

经过大量的研究和尝试,我想出了以下解决方案(也改进了 C++20 concepts 功能):

After a lot of research and tries, I came up with the following solution (improved also with C++20 concepts feature):

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++ 中迭代类继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆