我一直在研究用C ++编写的服务器,并为套接字和所有服务器使用SFML网络。但是,我已经遇到了一些死胡同。 SFML套接字是不可复制的,因此不能存储到大多数(我知道的所有)stl容器中。
所以,我很快就跳到了使用指针的想法然后它让我觉得我应该使用RAII,但我讨厌智能指针并且需要存储更多信息,而不仅仅是指向Socket类的指针。
我编写了一个Client类,它封装了套接字并在调用Client类的析构函数时将其删除,这很好,花花公子......我记得stl容器会复制我的类,删除指针然后我留下一个悬垂的指针。
那么,无论如何我可以解决不可复制的问题吗?我需要将指针存储在类中,我需要该类来销毁已分配的内存。
我想我可以使用复制构造函数将复制的类指针设置为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) ) );
}
}
}
};
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;
};
答案 0 :(得分:1)
首先,您是否可以使用C ++ 11是一个改变游戏规则的行为。
在C ++ 11中,您有 move 的概念。与复制不同,移动不是关于重复,而是关于转移。所有标准容器都适用于可移动的不可复制类。
可移动类的一个例子:
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的土地上,你会遇到一些麻烦。最简单的解决方案是使用经理类: