繁体   English   中英

对象管理器的最佳实践

[英]Best practices with object manager

我是c ++编程的新手,我正在编写一个多人游戏的对象管理器,但我对如何管理客户端对象有一些疑问。 客户端对象由连接的客户端参数(如IP,连接时间,接收数据等)组成。

为了避免内存碎片,我打算分配一个允许客户端最大数量的对象池。 为此,我正在编写一个像这样的客户端对象管理器:

ClientManager.h

#include "Client.h"

class ClientManager { 
public: 
static void init(int max); //initialize pool (allocate memory) 
static void dispose(); //dispose pool (deallocate memory) 
static bool add(int socketFd); //add connected client by its socket file descriptor 
static bool remove(int socketFd); //remove connected client by its socket fd
static Client& get(int socketFd); //get the client object by its socket fd

private: 
Client* clientList; //array of allocated clients objects
int maxClient; //max number of connected clients allowed

请注意,此类将仅以静态方式调用,因此没有构造函数/析构函数。 此类必须是静态的,因为必须在不同类型的对象之间读取/修改客户端数据。

实现将是这样的:

ClientManager.cpp

void ClientManager::init(int max) {
maxClient = max;
clientList = new Client[maxClient];
}

void ClientManager::dispose() {
maxClient = 0;
delete [] clientList;
clientList = NULL;
}

bool ClientManager::add(int socketFd) {
//search pool for non-initialized object
//if(there is a non-initializes object) { initialize it with socketFd and return true}
//else return false;
}

bool ClientManager::remove(int socketFd) {
//search pool for socketFd
//if(socketFd found) { clear object (make it non-initialized) and return true}
//else return false
}

Client& ClientManager::get(int socketFd) {
//search for object position
if(pos) return clientList[pos];
else ???????
}

现在,如何在get函数中管理对象返回? 是参考最好的选择吗? 我不想返回指针,但如果它是我的最后一个选项,我可以忍受它。 我想我可以确保我只在池中获得注册(初始化)对象,如果是这样,那么检查get函数是否必要? 我不想要断言,因为我希望代码是健壮的,而不是在运行时停止(我是C ++的新手,所以如果我说错了,请纠正我)。

在主程序中,我在考虑如下:

Daemon.cpp

#include "ClientManager.h"

int main(...) {
ClientManager::init(100);

while(1) {
//do server stuff
//get onConnect event (new client is connecting)
//get onDisconnect event (connected client has gone offline)
//get onDataReceived event (connected client has sent data)
}
}

void onConnect(int socketFd) {
ClientManager::add(socketFd);
}

void onDisconnect(int socketFd) {
ClientManager::remove(socketFd);
}

void onDataReceived(int socketFd) {
do_something(ClientManager::get(socketFd).data);
}

我做得对吗? 谢谢

笔记:
1)这个代码在我的脑海里,我在这里打字,所以我可能忘记了一些东西。
2)程序只会被终止(我正在使用linux)终止,因此ClientManager dispose方法不会在主程序中显式调用(因为它是一个静态类)。 再说一遍,如果我说错了,请告诉我!
3)抱歉我的英文不好:)

几点评论:

  • 使用std :: vector来保存客户端对象,而不是某种本地结构。 它会让你的生活更轻松
  • 我认为如果get()返回一个引用就好了,前提是用户确实知道如果引用挂起太长时间引用就会失效
  • 如果元素不存在,我会在get()抛出异常; 这就是异常的含义,它将允许您在适当的级别处理缺少的元素

对于(2),您可以处理适当的信号并调用dispose()。 我想你可能确实想在退出之前关闭套接字。

使许多成员静态不会使它成为“静态类”。 它只是一个类似于任何其他类的类,具有静态成员函数。 您无论如何都不需要这样做:只需将ClientManager设置为普通类并在游戏中创建其中一个。

我建议使用std :: vector而不是你自己的数组。 这将使您的代码更加健壮,并使您更容易设置客户端,使用适当的构造函数为每个客户端,而不是使用某种默认构造函数。

你不应该担心内存碎片 - 这是一个如此深奥的低级细节,你甚至不应该考虑它。 它对你来说是一个问题的机会是天文数字很小。 但即使它是一个问题,我们也无法根据您在此处发布的内容进行诊断,因为我们不知道什么构成了Client类。 如果Client类本身引用其他地方的各种内存,那么在ClientManager类中有一个精心管理的池是没有意义的。 在此阶段,您应该专注于编写健壮且正确的代码,并在需要时进行优化。

您也可以从ClientManager :: get返回一个指针。 请确保在使用之前检查它是否为null。 如果选择不同的接口,则可以完全取消从ClientManager返回客户端的需要,例如。 将操作do_something与数据一起传递给ClientManager的成员,该成员将查找客户端并在找到客户端时调用操作,如果不是,则报告错误。 (虽然没有充分的理由说明为什么找不到它,如果你的ClientManager是正确的。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM