请考虑以下两个代码段, 第一个:
#include "pch.h"
#include <memory>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
class tcp_connection : public std::enable_shared_from_this<tcp_connection>
{
public:
typedef std::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
//second example only differs by replacing the above line with the below one
//return std::make_shared<tcp_connection>(io_service);
}
private:
tcp_connection(boost::asio::io_service& io_service) //private constructor
: socket_(io_service)
{
}
tcp::socket socket_;
};
int main()
{
return 0;
}
第二行与第一行的区别仅在于一行,即注释行。
使用MSVC 2017和boost :: asio 1.68,第一个版本可按预期工作,而第二个版本未编译,吐出诸如“不允许使用不完整的类型tcp_async”之类的错误。
我的问题是:
答案 0 :(得分:6)
您显示的代码中的问题源于您的类型的构造函数是私有的。
在编写new tcp_connection(io_service)
时,构造函数将在tcp_connection
本身具有访问权限的范围内被引用。
但是,std::make_shared
(或它可能采用的任何实现细节)都不能访问私有构造函数,因此它无法初始化要具有共享指针管理的对象。
如果初始化格式正确,则std::make_shared
与std::enable_shared_from_this
会很好地工作,但是私有构造函数会使它格式错误。
一个常见的解决方法是使用Passkey idiom。归结为一个公共变量,但是它接受一个私有类型的参数。想要这样的 1 :
class tcp_connection2: public std::enable_shared_from_this<tcp_connection2>
{
struct key{ explicit key(){} };
public:
typedef std::shared_ptr<tcp_connection2> pointer;
static pointer create(int io_service)
{
return std::make_shared<tcp_connection2>(io_service, key{});
}
tcp_connection2(int io_service, key) //private constructor, due to key
{
}
};
1 -我稍微修改了您的类定义,以使其他人可以更轻松地复制,粘贴和测试它。但是,相同的原理也可以应用于您的代码。