带有移动构造函数的 C++ 接口的适配器 class
adapter class for C++ interface with move constructor
我正在尝试为接口 class 编写 adapter
class 接受 a) 接口的实现,它应该是堆栈分配的(所以没有 new/delete 应该需要从外部进行处理,适配器本身可以使用 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 lambda\n"; 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();
^
- 我完全不明白这个错误,非常感谢您的解释
- 我怎样才能真正正确地实现
adapter(interface&&)
构造函数?我可能需要在堆上创建对象的副本,否则在 adapater
构造函数 之后它不会持久化
在 ideone 上测试:http://ideone.com/Gz3ICk 使用 C++14 (gcc-5.1)
PS:是的,adapter
class 缺少应删除从 lambda 构造函数
创建的 obj
的析构函数
试试
adapter b {implementation()};
问题在于
adapter b(implementation());
没有被解释(如果我没记错的话)类型为 adapter
的对象的实例化,而是被解释为名称为 b
的函数的声明 receive an object of type implementation
takes a single (unnamed) parameter which is also a function, returning type implementation and take no parameters [Songyuanyao 更正] 和 return一个adapter
.
我知道解决这个歧义的两种方法
1) 添加一对括号
adapter b((implementation()));
2) 使用基于大括号的新统一初始化样式
adapter b {implementation()};
我建议使用表格 2,因为您使用的是 C++11,并且(恕我直言)它更清晰。
---添加了解决生命周期问题的例子---
要解决impl
的copy/clone/lifetime,嗯……你用的是指向纯虚基的指针class;我看到的唯一解决方案是克隆派生的 class.
我提出一个解决方案
1) 将 adapter
中的 obj
从 interface *
切换为 std::unique_ptr<interface>
(以避免释放问题)
2) 在 interfece
中添加了一个纯虚拟成员 clone()
即 return 一个 std::unique_ptr<interface>
3) 添加了一个中间模板 class (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 lambda\n"; return 99; });
a.obj->hello();
adapter b { implementation() };
b.obj->hello();
return 0;
}
p.s.: 对不起我的英语不好
我正在尝试为接口 class 编写 adapter
class 接受 a) 接口的实现,它应该是堆栈分配的(所以没有 new/delete 应该需要从外部进行处理,适配器本身可以使用 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 lambda\n"; 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();
^
- 我完全不明白这个错误,非常感谢您的解释
- 我怎样才能真正正确地实现
adapter(interface&&)
构造函数?我可能需要在堆上创建对象的副本,否则在adapater
构造函数 之后它不会持久化
在 ideone 上测试:http://ideone.com/Gz3ICk 使用 C++14 (gcc-5.1)
PS:是的,adapter
class 缺少应删除从 lambda 构造函数
obj
的析构函数
试试
adapter b {implementation()};
问题在于
adapter b(implementation());
没有被解释(如果我没记错的话)类型为 adapter
的对象的实例化,而是被解释为名称为 b
的函数的声明 receive an object of type takes a single (unnamed) parameter which is also a function, returning type implementation and take no parameters [Songyuanyao 更正] 和 return一个implementation
adapter
.
我知道解决这个歧义的两种方法
1) 添加一对括号
adapter b((implementation()));
2) 使用基于大括号的新统一初始化样式
adapter b {implementation()};
我建议使用表格 2,因为您使用的是 C++11,并且(恕我直言)它更清晰。
---添加了解决生命周期问题的例子---
要解决impl
的copy/clone/lifetime,嗯……你用的是指向纯虚基的指针class;我看到的唯一解决方案是克隆派生的 class.
我提出一个解决方案
1) 将 adapter
中的 obj
从 interface *
切换为 std::unique_ptr<interface>
(以避免释放问题)
2) 在 interfece
中添加了一个纯虚拟成员 clone()
即 return 一个 std::unique_ptr<interface>
3) 添加了一个中间模板 class (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 lambda\n"; return 99; });
a.obj->hello();
adapter b { implementation() };
b.obj->hello();
return 0;
}
p.s.: 对不起我的英语不好