如何拆分大开关语句

时间:2011-09-22 12:01:52

标签: c++ networking

我正在制作一个在线游戏,当我从客户端收到数据时,我会收到几个“结构”(比如“我的位置”,“使用药水23”,“攻击玩家45”,“谈话bla bla”,注销等),这些结构被安全地读取并放入结构中,推送到列表中(稍后,当服务器有时间时)处理。

问题是处理是一个Big switch语句(切换到一种枚举 - “RTTI”),我有超过60种不同的结构,它们都是不同的。

因此,包含处理代码的.cpp开始变得相当大,并且随着我不断向游戏添加功能(c ++在4000-5000行之间),它不会随时缩小。

我可以看到一个简单的解决方案,每个案例在另一个文件中调用一个函数但是字面意思(注意到harriyott,字面意思是我的项目,我的驱动器将充满新文件)爆炸文件的数量我需要知道并跟踪。

我知道我可以在几个fileN.cpp中删除它(案例)并在处理文件中生成'#include“file1.cpp”#include“file2.cpp”等,但这看起来非常糟糕。 而且我已经“想出”以规避这个问题的任何其他方式似乎太过“hacky”。​​

所以问题是,你如何很好地拆分一个大的转换声明?

6 个答案:

答案 0 :(得分:4)

你可以

  • 使用从枚举到处理函数的映射替换开关(函数实现本身可以在同一个文件中,或根据您的喜好在不同的文件中),或者
  • (面向对象的解决方案越多)使得所讨论的所有结构继承自声明处理程序方法的公共接口,使每个实现在其特定的处理程序方法中具有所需的功能,然后以多态方式调用它们。

答案 1 :(得分:1)

使用map_list_of。像这样:

class Base
{
public:
  virtual ~Base(){}
  virtual void foo()=0;
};
class D1 : public Base
{
  virtual void foo() { /*1*/ };
};
class D2 : public Base
{
  virtual void foo() { /*2*/ };
};

Base* Lookup( const int v )
{
  const static map< int,Base* > next = map_list_of( 1,new D1)(5,new D2);
  return next[v];
}

答案 2 :(得分:1)

在我看来,boost :: variant可以让你的生活更轻松。您将主事件类型构建为类的boost :: variant,然后使用static_visitor类来实现您的魔力。本质上是一个开关,但在逻辑上很好地包装和类型安全。

答案 3 :(得分:1)

为什么不去另一种方法,你有一个map(hashmap),其中消息id作为键映射到处理程序。每个处理程序处理一条消息。

然后处理将根据传入消息(id)进行查找,并调用找到的处理程序。

答案 4 :(得分:1)

您可以使用具有抽象函数的类,例如process。而不是结构创建适当的类。然后,而不是switch所有你需要做的就是为列表中的元素调用`process``函数。

答案 5 :(得分:1)

使用面向对象的方法,使用select ONLY选择适当的类。设计将更加灵活,稍后当您添加更多动作,对象或其他内容时,它将获得回报。

  

我收到了几个'结构'(说'我的位置','使用药水23',   '攻击玩家45','谈论bla bla',退出等),

你已经可以发现一些示范性的类:如所有魔药的GameObject等,或玩家和怪物的GameActor。稍后,您可以拥有一些GameAction类,可以接受操作的“源”和“目标”,如Ax和Ogre。您可以UseActionAttackAction继承GameActionsetSourceOfAction(obj)setDestinationOfActon(o)doAction()方法。

最后你根本不需要臃肿switch(),或者可能选择几个基类。我认为这是方法。