2015-12-27 55 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'所需的構造函數。所以決定在閱讀你的答案後保留我的原始代碼,謝謝! –

相關問題