c++ - 迭代 C++ 中的类继承

标签 c++ variadic-templates multiple-inheritance crtp fold-expression

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

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

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

简短示例:

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基类的功能/属性。

  • 一个 实例 (供我实际使用)可以在this commit中找到.

    编辑:

    Thanks to @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<>>>();一个 实例 (供我实际使用)可以在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] 我们可以在几行代码中实现它。

    优点与我最初的想法相比:
  • 对象创建行现在更加清晰和合乎逻辑:
    之前: 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_assertfold 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++20 concepts 功能进行了改进):
    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++ 中的类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62091515/

    相关文章:

    c++ - 使用位移运算将两个变量相乘

    c++ - 如何为 std::array 声明一个全局编译时常量?

    c++ - 对模板类链使用可变参数模板来生成序列化

    c# - 如何模拟多重继承并使用反射来优化此代码?

    c++ - 通过类型转换 C++ 向其添加 0 后,标签文本不会在 Windows 窗体上更新

    c++ - 转发参数

    c++ - 如何创建具有任意数量(编译时确定)容器的内存池?

    java - 如何避免由于无法使用多重继承而导致重复代码。 hibernate

    python - 为什么我不能从 Python 中的 dict AND Exception 继承?

    c++ - 二进制搜索树读取字符串? C++