2013-09-28 23 views
0

我一直在用C++編寫的服務器上工作,並且使用SFML網絡連接套接字和所有服務器。但是,我已經爲我陷入了一個死路一條。 SFML套接字是不可複製的,因此無法存儲到大多數(我知道的)stl容器中。因此,我很快跳到使用指針的想法,然後它打我說我應該使用RAII,但是我討厭智能指針,並且需要存儲更多信息,而不僅僅是指向Socket類的指針。不可複製的類

我寫了一個Client類,它封裝了套接字,並在Client類的析構函數被調用時刪除它,這很好,很花哨。直到我記得stl容器會複製我的類,刪除指針,然後我會留下一個晃來晃去的指針。

那麼,無論如何,我可以解決非copyables?我需要將指針存儲在類中,我需要該類來銷燬分配的內存。

我想我可以使用複製構造函數來將複製的類的指針設置爲null,但我找不到這樣做的方法。

相關信息:

所有的

Client.cpp

Client::Client() 
{ 
}; 

Client::Client(sf::TcpSocket* in_Connection) 
{ 
    m_Connection = in_Connection; 
    m_IPAddress = m_Connection->getRemoteAddress().toString(); 
    m_AccountName = "NOACCOUNT"; 
    m_CharacterName = "NOCHARACTER"; 
}; 

Client::~Client() 
{ 

    m_Connection->disconnect(); 
    delete m_Connection; 
}; 

//getters 
sf::TcpSocket* Client::getConnection() 
{ 
    return m_Connection; 
}; 

std::string Client::getIPAddress() 
{ 
    return m_IPAddress; 
}; 

std::string Client::getAccountName() 
{ 
    return m_AccountName; 
}; 

std::string Client::getCharacterName() 
{ 
    return m_CharacterName; 
}; 

//setters -- Account Name and Character Name are the only two that can be changed during a connection. 
void Client::setAccountName(std::string in_AccountName) 
{ 
    m_AccountName = in_AccountName; 
}; 

void Client::setCharacterName(std::string in_CharacterName) 
{ 
    m_CharacterName = in_CharacterName; 
}; 

//Copy Constructor <--This defintely won't work and I know that, haha. 
Client::Client(const Client& that) 
{ 
    m_Connection = new sf::TcpSocket(); 
    *m_Connection = *that.m_Connection; // Cannot copy non-copyable 
    m_IPAddress = that.m_IPAddress; 
    m_CharacterName = that.m_CharacterName; 
    m_AccountName = that.m_AccountName; 
}; 

Server Accept Function

void Server::AcceptConnections() 
{ 
    sf::TcpSocket* Socket = new sf::TcpSocket(); 

    if(m_Listener.accept(*Socket) == sf::Socket::Done) 
    { 
     if(Socket != NULL) 
     { 
      std::string IPAddress = Socket->getRemoteAddress().toString(); 

      if(m_Connections.find(IPAddress) == m_Connections.end()) 
      { 
       std::cout << IPAddress; 
       std::cout << " Has Connected."; 
       std::endl(std::cout); 

       m_Connections.insert(std::make_pair(IPAddress, Client(Socket))); 
      } 
     } 
    } 
}; 

+0

「我應該使用RAII引用/指針的實例,但我討厭聰明的指針「 - 似乎你有點衝突。 – john

+0

難道我們不時都在? :P –

+0

使用智能指針。這正是他們存在的原因。 –

回答

1

首先,是否可以使用C++ 11與否是一個改變遊戲規則。

在C++ 11中,您有移動的概念。與複製不同,移動不是複製而是轉移。所有標準容器都適用於可移動的非可複製類。

活動類的一個實例:

class Client { 
public: 
    Client(Client const&) = delete; // non copyable 
    Client& operator=(Client const&) = delete; // non copy assignable 

    Client(Client&&) = default; // movable 
    Client& operator=(Client&&) = default; // move assignable 

private: 
    std::unique_ptr<sf::TcpSocket> _socket; 
}; 

而且你的問題就解決了。


如果你被卡在C++ 03的土地上,那麼你會遇到一些麻煩。最簡單的辦法是使用一個管理器類:

  • 經理擁有
  • 用戶實例的永遠只能操縱它
+0

謝謝,我在實現移動語義方面遇到了一些麻煩,但我很快就會在這裏看到它。 –

+0

@ user2807377:如果您使用'unique_ptr'並依賴'= default',那麼您確實沒有任何東西要實現。 –

+0

不幸的是,MSVC++ 2012似乎沒有實現默認和刪除,就像它們在您的代碼中定義的一樣,所以我將複製和複製賦值運算符設爲私有,然後實現了移動和移動賦值運算符,並且它的運行完美無瑕。 –