如何在C ++中编写java接口的参数级实现?

时间:2015-02-19 16:16:03

标签: c++

Java中的一个好处是实现接口。例如,请考虑以下代码段:

interface SimpleInterface()
{
public: void doThis();
}

...
SimpleInterface simple = new SimpleInterface()
{
@Override public doThis(){ /**Do something here*/}
}

我能看到这一切的唯一方法是通过C ++中的Lambda或传递函数实例<>去上课。但我实际上是在检查这是否可行?我有实现特定接口的类,这些接口只包含1-2个方法。我无法为其编写新文件或将方法添加到接受函数<>的类中。或lambda,以便它可以决定做什么。这是严格的C ++限制吗?会不会得到支持?

不知何故,我想写这样的东西:

thisClass.setAction(int i , new SimpleInterface()
{
protected:
virtual void doThis(){}
});

但有一点是我没有检查C ++ 14的最新规范,我想知道这是否可行。

谢谢!

4 个答案:

答案 0 :(得分:6)

  

它会得到支持吗?

你的意思是,语言设计师是否会添加一个肮脏的黑客,其中一种语言存在的唯一原因是因为那些设计师太愚蠢而无法添加他们实际需要的功能?

不在这个特定情况下。

您可以创建从中派生的派生类,然后使用lambda,然后在各个调用站点使用它。但是你仍然需要为每个接口创建一个转换器。

struct FunctionalInterfaceImpl : SimpleInterface {
    FunctionalInterfaceImpl(std::function<void()> f)
        : func(f) {}
    std::function<void()> func;
    void doThis() { func(); }
};

答案 1 :(得分:2)

您似乎认为每个类都需要单独的.h.cpp文件。 C ++允许您在任何范围定义类,包括函数的本地类:

void foo() {
  struct SimpleInterfaceImpl : SimpleInterface
  {
  protected:
    void doThis() override {}
  };

  thisClass.setAction(int i , new SimpleInterfaceImpl());
}

当然,你有一个裸体new,这可能是一个坏主意。在实际代码中,您需要在本地分配实例,或使用智能指针。

答案 2 :(得分:1)

这确实是一个&#34;限制&#34; C ++(和C#,因为我前段时间做过一些研究)。匿名java类是它的独特功能之一。

您可以模拟的最接近方式是使用函数对象和/或本地类型。因此,C ++ 11及更高版本提供了lambdas,它们是这两件事的语义糖,并为我们节省了大量的文字。谢天谢地,在c ++ 11之前必须为每个小东西定义一个类型。

请注意,对于由单个方法组成的接口,函数对象/ lambdas / delegates(C#)实际上是一种更清洁的方法。 Java在这种情况下使用接口作为&#34;限制&#34;它自己的。将单方法接口用作C ++中的回调将被视为Java-ism。

本地类型实际上是一个非常好的近似值,唯一的缺点是你被迫命名类型 (参见编辑)(一个令人厌烦的义务,一个人采取在使用C系列的静态语言时。)

您不需要使用new分配对象以多态方式使用它。它可以是一个堆栈对象,您通过引用传递(或指针,以获得额外的时间错误)。例如:

struct This {};

struct That {};

class Handler {
  public:
    virtual ~Handler ();
    virtual void handle (This) = 0;
    virtual void handle (That) = 0;
};

class Dispatcher {
    Handler&    handler;
  public:
    Dispatcher (Handler& handler): handler(handler) { }

    template <typename T>
    void dispatch (T&& obj) { handler.handle(std::forward<T>(obj)); }
};

void f ()
{
    struct: public Handler {
        void handle (This) override { }
        void handle (That) override { }
    } handler;
    Dispatcher dispatcher { handler };
    dispatcher.dispatch(This {});
    dispatcher.dispatch(That {});
}

另请注意c ++ 11提供的override说明符,它与@Override注释的目的大致相同(如果此成员函数(方法)不具有此错误,则会生成编译错误实际上覆盖任何东西)。

我从未听说过这个功能得到支持甚至讨论过,我个人认为它甚至不被视为C ++社区的一个功能。

编辑在完成这篇文章之后,我意识到没有必要自然地命名本地类型,所以这个例子变得更加java友好。唯一的区别是您无法在表达式中定义新类型。我已相应更新了这个例子。

答案 3 :(得分:-1)

在c ++中,接口是具有纯虚函数的类等等

class Foo{
   virtual Function() = 0;
};

每个继承此类的类都必须实现此函数。