0

我一直在研究用 C++ 编写的服务器,并使用 SFML 网络连接套接字和所有内容。但是,我遇到了一些死胡同。SFML 套接字是不可复制的,因此不能存储到大多数(我所知道的所有)stl 容器中。

所以,我很快就想到了使用指针,然后突然想到我应该使用 RAII,但我讨厌智能指针,需要存储更多信息,而不仅仅是指向 Socket 类的指针。

我写了一个客户端类,它包装了套接字并在调用客户端类的析构函数时将其删除,这很好而且花花公子..直到我记得 stl 容器将复制我的类,删除指针然后我会留下一个悬空的指针。

那么,无论如何我可以绕过不可复制的东西吗?我需要将指针存储在类中,并且我需要类来销毁分配的内存。

我想我可以使用复制构造函数将复制的类的指针设置为空,但我找不到这样做的方法。

以供参考:

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) ) ); 
            }
        }
    }
};

4

1 回答 1

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 领域,你会遇到一些麻烦。最简单的解决方案是使用管理器类:

  • 经理拥有该实例
  • 实例的用户只操作它的引用/指针
于 2013-09-28T14:40:39.753 回答