【问题标题】:How to tell a C++ mixin the interface it implements如何告诉 C++ mixin 它实现的接口
【发布时间】:2016-06-14 12:32:30
【问题描述】:

我有一个接口和一个实现它的类:

class InterfaceA
{
public:
    enum Enum { X, Y, Z };
    virtual void foo(Enum &) = 0;
    virtual void bar() = 0;
};

class ClassA : public InterfaceA
{
public:
    virtual void foo(Enum & a) { 
        a = X;
    }
    virtual void bar();
};

我需要在一个方面扩展 InterfaceA 实现类的功能。据我了解,这就是 mixin 的用途。

例如foo() 应该在某些条件下更改其参数值。这是我的做法:

template <typename T>
class Mixin : public T
{
public:
    virtual void foo(Enum & a) { 
        T::foo(a);
        if (a == X){
            a = Y;
        }
    }
};

问题是,除非我将范围前缀写入接口类中定义的标识符或像这样对它们进行类型定义,否则它不会编译:

template <typename T>
class Mixin : public T
{
public:
    typedef InterfaceA::Enum Enum;
    virtual void foo(Enum & a) { 
        T::foo(a);
        if (a == InterfaceA::X){
            a = InterfaceA::Y;
        }
    }
};

如果接口定义中的此类类型很少,这没什么大不了的。但是如果有很多,它可能会变得丑陋。我希望代码能够反映 Mixin 通过设计操纵 InterfaceA 对象的事实。不幸的是,从 InterfaceA 继承 Mixin 引入了一个我最好避免的“可怕的钻石”。这可能吗?

【问题讨论】:

    标签: c++ mixins


    【解决方案1】:

    EnumXY 应该是依赖类型名。

    您可以使用static_assert 强制继承。

    template <typename T>
    class Mixin : public T
    {
    public:
        static_assert(std::is_base_of<InterfaceA, T>::value,
                      "T should inherit from InterfaceA");
    
        virtual void foo(typename T::Enum & a) { 
            T::foo(a);
            if (a == T::X){
                a = T::Y;
            }
        }
    };
    

    【讨论】:

    【解决方案2】:

    我想你应该使用虚拟继承;这应该可以避免“可怕的钻石”问题。

    类似

    class InterfaceA
     {
       public:
          enum Enum { X, Y, Z };
          virtual void foo(Enum &) = 0;
          virtual void bar() = 0;
     };
    
    class ClassA : public virtual InterfaceA
     {
       public:
          virtual void foo(Enum & a) { 
             a = X;
          }
          virtual void bar() {
          }
     };
    
    template <typename T>
    class Mixin : public T, public virtual InterfaceA
     {
       public:
          virtual void foo(Enum & a) { 
             T::foo(a);
             if (a == X){
                a = Y;
             }
          }
     };
    
    
    int main ()
     { 
       Mixin<ClassA> m;
    
       return 0;
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2015-05-06
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多