2015-12-27 53 views
0

我在写一个C++ websocket服务器库。在我提供的一个例子中,我使用了两个类session_basesession。我这样做的目的是为了在父类中初始化tcp::socket对象(使用移动构造函数),然后将引用传递给存储此引用以供将来使用的ws::session<tcp::socket>父类。我创建ws:session作为模板类的原因是我可以使用boost::asio::ssl::stream以及tcp套接字。将对未初始化对象的引用传递给超类构造函数,然后用它的移动构造函数初始化所述对象?

难道是有效有tcp::socket对象session类的成员,传递一个参考这个未初始化对象到ws::session构造方法(不使用tcp::socket尚未 - 仅存储参考),然后初始化tcp::socket对象之后使用套接字移动构造函数?

当前代码:

using boost::asio::ip::tcp; 

class session_base { 
public: 
    session_base(tcp::socket socket) : socket_(std::move(socket)) { } 
protected: 
    tcp::socket socket_; 
}; 

using T = tcp::socket; 
class session : public session_base, public ws::session<T> { 
public: 
    session(tcp::socket socket) : 
     session_base(std::move(socket)), ws::session<T>(socket_) 
    { 
     std::cout << "session()\n"; 
    } 

    ~session() { 
     std::cout << "~session()\n"; 
    } 

private: 
    void on_open() override { 
     std::cout << "WebSocket connection open\n"; 
    } 

    void on_msg(const ws::message &msg) override { 
     /* Do stuff with msg */ 

     read(); 
    } 

    void on_close() override { 
     std::cout << "WebSocket connection closed\n"; 
    } 

    void on_error() override { 
     std::cout << "WebSocket connection error\n"; 
    } 
}; 

建议代码:

下提出的代码对我的作品,但我想知道这是定义的行为,并建议。

using boost::asio::ip::tcp; 

using T = tcp::socket; 
class session : public ws::session<T> { 
public: 
    session(tcp::socket socket) : 
     ws::session<T>(socket_), socket_(std::move(socket)) 
    { 
     std::cout << "session()\n"; 
    } 

    ~session() { 
     std::cout << "~session()\n"; 
    } 

private: 
    tcp::socket socket_; 

    void on_open() override { 
     std::cout << "WebSocket connection open\n"; 
    } 

    void on_msg(const ws::message &msg) override { 
     /* Do stuff with msg */ 

     read(); 
    } 

    void on_close() override { 
     std::cout << "WebSocket connection closed\n"; 
    } 

    void on_error() override { 
     std::cout << "WebSocket connection error\n"; 
    } 
}; 

完整的源:https://github.com/alexyoung91/ws

+0

似乎与[将C++对象传递给它自己的构造函数合法吗?](http://stackoverflow.com/q/32608458/1708801) –

+1

将代码放在问题中,而不是链接到您的代码。 – 1201ProgramAlarm

回答

1

如果ws::session构造仅存储到插座的引用但不使用参考,例如,呼叫插座构件的功能或访问数据成员则程序是井-formed。该标准称这是对3.8/6([basic.life/6])中分配的存储器的引用:

类似地,在对象的生命周期开始之前,但在对象将占用的存储之后已被分配,或者在对象的生命周期结束之后并且在重新使用或释放​​对象所占用的存储之前,可以使用引用原始对象的任何glvalue,但仅以有限的方式使用。正在建造或破坏的物体,见12.7。否则,这样的glvalue指的是分配的存储(3.7.4.2),并且使用不依赖于它的值的glvalue的属性是明确的。该方案已未定义的行为,如果:

- 左值到右值转换(4.1)被施加到这样的glvalue,

- 所述glvalue用于访问非静态数据成员或调用非对象的-static成员函数,或

- 所述glvalue隐式转换(4.10)到一个参照本发明的基类型,或

- 所述glvalue用作的static_cast(5.2操作数。 9)除非最终转换为cvchar&CVunsigned char&,或

- 所述glvalue用作的dynamic_cast(5.2.7)的操作数或作为typeid操作数。

请注意,存储必须在获得引用时分配,并且在调用session构造函数时必须分配。

尽管如此,我不会推荐这种方法。主要是因为在构造函数ws::session中很容易忘记所传递的引用是指一个尚未初始化的对象,并在稍后引入一个错误。更好地使用base-from-member idiom并保留您的原始代码。

+0

我试图使用boost :: base_from_member,它不必编写session_base类,但我不认为它支持移动'tcp :: socket'所需的构造函数。所以决定在阅读你的答案后保留我的原始代码,谢谢! –

相关问题