类内不可复制

时间:2013-09-28 13:43:00

标签: c++ sockets pointers stl sfml

我一直在研究用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; };

1 个答案:

答案 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的土地上,你会遇到一些麻烦。最简单的解决方案是使用经理类:

  • 经理拥有实例
  • 实例的用户只能处理对它的引用/指针