如何在它实现的接口中告诉C ++ mix

时间:2016-06-14 12:32:30

标签: c++ mixins

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

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实现类的功能。据我所知,这就是mixins的用途。

E.g。 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引入了一个“可怕的钻石”,我最好避免使用它。这可能吗?

2 个答案:

答案 0 :(得分:0)

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

这样的东西
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;
 }

答案 1 :(得分:0)

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;
        }
    }
};