gpt4 book ai didi

c++ - 一个程序有很多系统(类)。使系统可以通过类名调用其他人?

转载 作者:行者123 更新时间:2023-11-28 05:40:07 27 4
gpt4 key购买 nike

假设我有一个游戏引擎。

假设它包含类GraphicGamePlayPhysics 系统。
(真实案例是20+系统。)

这三个都是从System派生的。

这是简单初始化的草稿。

main(){
Game_Engine* engine = new Game_Engine();
Graphic* sys1= new Graphic(engine); //set to System::engine_pointer
GamePlay* sys2= new GamePlay(engine);
Physics* sys3= new Physics(engine);
engine->addSystem(sys1); //add to Game_Engine's hash map
engine->addSystem(sys2);
engine->addSystem(sys3);
}

然后,我想让所有系统都可以互相调用。前任。 Graphic可以调用GamePlay

所以我将 addSystem() 设计为:-

class Game_Engine {  
std::unordered_map<std::type_index,Sys*> hashTable;
void addSystem (System* system){
hashTable.add( std::type_index(typeid(*system)), system );
}
template <class SysXXX> SysXXX* getSystem(){
return hashTable.get(std::type_index(typeid(SysXXX)) );
}
}

结果是每个System可以只用类名互相调用:-

class Graphic : public System {
void call_me_every_time_step(){
engine_pointer->getSystem<GamePlay>()->... do something ;
}
}

现在,它如我所愿,但是

  1. 听说 typeid 对性能不好。

  2. Game_Engine.h 现在必须 #include 所有 Graphic.hGamePlay.hPhysics.h ,因此编译时间增加。
    (我试图不包括它们 -> 3 个派生系统的 typeid 将返回错误的结果。)

是否可以避免这些缺点?怎么样?
还有其他缺点吗?
这首先是一个糟糕的设计吗?如果是这样,什么是好的设计?(因为我在 C++ 方面的经验非常有限。)

编辑 1:下面部分对 gudok 的回答的回应

为每个系统添加一定的get/set函数是我做的。

但是,我意识到,当系统越多时,管理就越难,至少对我而言是这样。

我避开了它,改用了模板代码,如上所述。

对于gudok的解决方案,单个系统会增加程序员的工作量如下:-

  1. 在“GameEngine”中添加字段声明
  2. 再添加一个返回某个系统的函数
  3. 重命名类时,例如通过使用自动重构工具将“图形”更改为“渲染”,我也必须将 getGraphics() 重命名为 getRender()(以使代码可读)

对比题中的代码,单个系统只需1行。

engine->addSystem(new Graphics(engine));

这不是那么微不足道,尤其是当大多数系统都在更名,系统数量不断增加时。

编辑 2:对 gudok 增强答案的回应

使 GameEngine 派生自 SystemHolder{T} 可以将每个 System 的工作减少到 2 个地方:-

: public SystemHolder<Graphics>

engine.addSystem<Graphics>(new Graphics());  

不过还是2个地方。
有问题的代码只使用了 1 个地方。
因此,它还不够好,但感谢您的尝试!

最佳答案

为什么要使用 hash map 和 typeids 而不是在 GameEngine 中单独存储每个系统?从语义上讲,所有这些系统都做不同的事情。我宁愿做以下事情:

class GameEngine {
std::vector<System*> systems;

Graphics* graphics;
Gameplay* gameplay;
Physics* physics;

void setGraphics(Graphics* graphics) {
this->graphics = graphics;
this->systems.push_back(graphics);
}
Graphics* getGraphics() {
return this->graphics;
}

...
};

这个解决方案背后的想法是:

  1. 从语义的角度来看,每个系统都是不同的。当您从某个地方访问图形时,您很可能会使用特定于 Graphics 的函数而不是所有功能都通用 System秒。单独存储每个系统可以消除类型标识和不必要的类型转换的必要性。
  2. 当您需要以某种统一的方式处理所有系统时(例如,提前游戏时间),您可以使用 systems领域:

    for (auto it = systems.begin(); it != systems.end(); it++) {
    it->tick();
    }

编辑 这是增强的解决方案。您通过另外继承 GameEngine 添加新系统来自 SystemHodler .获取和设置特定 System 的实例使用 getSystem<T> 是统一的和 setSystem<T>方法——如您所愿。

#include <vector>

class System {
public:
virtual ~System() {}
};
class Graphics : public System {};
class Physics: public System {};

template<typename T>
class SystemHolder {
public:
T* getSystem() { return system; }
void setSystem(T* system) { this->system = system; }

private:
T* system;
};

class GameEngine: public SystemHolder<Physics>, public SystemHolder<Graphics> {
public:
template<typename T>
inline void addSystem(T* system) {
systems.push_back(system);
SystemHolder<T>::setSystem(system);
}

template<typename T>
inline T* getSystem() {
return SystemHolder<T>::getSystem();
}

private:
std::vector<System*> systems;
};

int main(int argc, char* argv[]) {
GameEngine engine;
engine.addSystem<Physics>(new Physics());
engine.addSystem<Graphics>(new Graphics());

engine.getSystem<Physics>();
engine.getSystem<Graphics>();
}

关于c++ - 一个程序有很多系统(类)。使系统可以通过类名调用其他人?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37298601/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com