带有move构造函数的c++接口适配器类



我正试图为接口类编写一个adapter类,该接口类接受a)接口的实现,应该是堆栈分配的(因此不应该从外部需要新的/删除处理,适配器本身可以使用new/delete)和b)一个lambda函数,该函数将由接口的各自实现调用。

#include <iostream>
#include <functional>
struct interface {
  virtual int hello() = 0;
};
struct implementation : public interface {
  virtual int hello() {
    std::cout << "hello()n";
    return 42;
  }
};
struct adapter {
  interface* obj;
  adapter(std::function<int()>&& func) {
    struct lambda : public interface {
      std::function<int()> func;
      lambda(std::function<int()> func_): func(func_) { }
      virtual int hello() {
        return this->func();
      }
    };
    this->obj = new lambda{func};
  }
  adapter(interface&& impl) {
    // TODO: pretty sure that's incorrect
    //       but can I somehow create a copy of "impl" on the heap?
    this->obj = &impl;
  }
};
int main() {
  adapter a([]() { std::cout << "hello from lambdan"; return 99; });
  a.obj->hello();
#if 0
  // ERROR
  adapter b(implementation());
  b.obj->hello();
#endif
  return 0;
}

这是我在启用adapter b部分时得到的错误。

prog.cpp: In function 'int main()':
prog.cpp:39:4: error: request for member 'obj' in 'b', which is of non-class type 'adapter(implementation (*)())'
  b.obj->hello();
    ^
  1. 我完全不明白这个错误,我希望你能解释一下
  2. 我如何才能真正正确地实现adapter(interface&&)构造器?我可能需要在堆上创建对象的副本,否则在adapater构造函数
  3. 之后它将无法持久。

在ideone: http://ideone.com/Gz3ICk与c++ 14 (gcc-5.1)测试

PS:是的,adapter类缺少一个析构函数,它应该删除从lambda构造函数创建的obj

Try with

adapter b {implementation()};

问题是

adapter b(implementation());

没有被解释为(如果我没记错的话)adapter类型对象的实例化,而是被解释为名称为b的函数声明,接收一个类型为implementation的对象,接受一个(未命名的)参数,该参数也是一个函数,返回类型实现,不接受参数[由songyuananyao更正],返回一个adapter

我知道两种方法来解决这个歧义

1)添加一对括号

adapter b((implementation()));

2)使用基于大括号

的新的统一初始化样式
adapter b {implementation()};

我建议使用形式2,因为你使用c++ 11并且(恕我直言)它更清晰。

——添加解决生命周期问题的示例——

要解决impl的复制/克隆/生存期,那么…您正在使用指向纯虚基类的指针;我认为唯一的解决方案是克隆派生类。

我提出了一个解决方案

1)将adapter中的objinterface *切换到std::unique_ptr<interface>(以避免释放问题)

2)在interfece中添加一个返回std::unique_ptr<interface>的纯虚拟成员clone()

3)添加了一个中间模板类(interHelper),只实现clone()一次

以下是我提出的解决方案

#include <memory>
#include <iostream>
#include <functional>
struct interface
 {
   virtual int hello() = 0;
   virtual std::unique_ptr<interface> clone () const = 0;
 };
template <typename D>
struct interHelper : public interface 
 {
   std::unique_ptr<interface> clone() const override
    { return std::unique_ptr<interface>(new D((const D &)(*this))); }
 };
struct implementation : public interHelper<implementation>
 {
   int hello() override
    {
      std::cout << "hello()n";
      return 42;
    }
 };
struct adapter
 {
   struct lambda : public interHelper<lambda>
    {
      std::function<int()> func;
      lambda (std::function<int()> func_): func(func_)
       { }
      int hello() override
       { return this->func(); }
    };
   std::unique_ptr<interface>  obj;
   adapter (std::function<int()>&& func) : obj { lambda{func}.clone() }
    { }
   adapter (interface&& impl) : obj { impl.clone() }
    { }
 };
int main()
 {
   adapter a([]() { std::cout << "hello from lambdan"; return 99; });
   a.obj->hello();
   adapter b { implementation() };
   b.obj->hello();
   return 0;
 }

注。:对不起,我的英语不好

相关内容

最新更新