具有方法重载的接口类?

时间:2018-05-16 22:21:26

标签: c++ oop c++11 templates variadic-templates

假设我有一些类型

class A {…};
class B {…};
class C {…};
...

我还有一些其他类可以对这些类型的对象进行各种操作

class process1
{
public:
    void do_stuff(std::vector<A>& …);
};

class process2
{
public:
    void do_stuff(std::vector<B>& …);
    void do_stuff(std::vector<C>& …);
};

...

这些&#34;过程&#34;类共享一些通用接口(do_stuff()),所以我自然想要创建一个类/模板来管理&#34;应该如何编写这些类。我想要像

这样的东西
template <class T>
class process_interface
{
public:
    virtual void do_stuff(std::vector<T>& …)
    {
        // Default implementation.
    }

    // I might also want this.
    // virtual void do_other_stuff(std::vector<T>& …) = 0;
};

process1process2从中衍生出来。通过这种方式,我说所有&#34;过程&#34;类应该有do_stuff(),并且由于存在默认版本,因此不必显式编写它。

但当然这不起作用,因为process2有两个版本的do_stuff()。 (其他一些&#34;流程&#34;类可能有更多。)那么有没有办法实现我想要的这个&#34;接口&#34;类/模板?我在考虑使用可变参数模板,但我认为它也不会起作用。

现在我的意思是:

class process_interface
{
public:
    template <class T>
    void do_stuff(std::vector<T>& …)
    {
        // Default implementation.
    }

    // template <class T>
    // void do_other_stuff(std::vector<T>& …)
    // {
    //     throw std::runtime_error("Nope.");
    // }
};

但它有问题。例如,do_stuff()不能是虚拟/纯虚拟。如果我有其他需要相同处理的方法,比如那里的do_other_stuff(),那么就没有办法强制子类为每个类型强制do_other_stuff() do_stuff() // file MyClass.js in an external package class MyClass { myfunc = () => { // do something } } // file in my project function myFunctionToBeTested() { const instance = new MyClass() instance.myFunc() } } on。

3 个答案:

答案 0 :(得分:1)

也许你可以使process2(以及所有需要更多do_stuff()类的可变自我继承类的类。

某事

template <typename...>
struct process2;

template <typename T>
struct process2<T> : public process_interface<T>
 { };


template <typename T0, typename ... Ts>
struct process2<T0, Ts...> : public process_interface<T0>,
                             public process2<Ts...>
 {
   using process_interface<T0>::do_stuff;
   using process2<Ts...>::do_stuff;
 };

以下是一个完整的工作示例

#include <vector>

class A {};
class B {};
class C {};
class D {};

template <typename T>
struct process_interface
 {
   virtual void do_stuff (std::vector<T> const &)
    { }
 };

struct process1 : public process_interface<A>
 { };

template <typename...>
struct process2;

template <typename T>
struct process2<T> : public process_interface<T>
 { };


template <typename T0, typename ... Ts>
struct process2<T0, Ts...> : public process_interface<T0>,
                             public process2<Ts...>
 {
   using process_interface<T0>::do_stuff;
   using process2<Ts...>::do_stuff;
 };

int main ()
 {
   process1           p1;
   process2<B, C, D>  p2;

   p1.do_stuff(std::vector<A>{});
   p2.do_stuff(std::vector<B>{});
   p2.do_stuff(std::vector<C>{});
   p2.do_stuff(std::vector<D>{});
 }

从C ++ 17开始,不需要自我递归process2:您可以使用解包usingprocess2简单地成为

template <typename ... Ts>
struct process2 : public process_interface<Ts>...
 {
   using process_interface<Ts>::do_stuff ... ; 
 };

答案 1 :(得分:1)

使用您的第一个版本并使用多重继承:

class process2 : process_interface<B>, process_interface<C> {
public:
    using process_interface<B>::do_stuff;
    using process_interface<C>::do_stuff;
};

注意using声明会将基类中的do_stuff带到process2本身,因此可以通过名称查找找到它们,然后参与重载解析。

A Complete Example

答案 2 :(得分:0)

这是一个很好的例子来说明为什么通过组合比继承更好地处理共同的功能共享。

这是获得你想要的东西的一种超级简单的方法,没有任何继承:

class common_interface {
   template <class T>
   void do_stuff(std::vector<T>& …)
   {
     //...
   }
};

class process_1 {
  common_interface common_;
public:
   void do_stuff(std::vector<A>& v) {
     common_.do_stuff(v);
     //...
   }
};

class process_2 {
  common_interface common_;
public:
   void do_stuff(std::vector<B>& v) {
     common_.do_stuff(v);
     //...
   }

  void do_stuff(std::vector<C>& v) {
     common_.do_stuff(v);
     //...
  }
};