which one would be better?
-
I'm working on a GAME SERVER program. there is a design problem confused me. Basic Situation: 1. the host object just as bellow has a lot of child objects. eg, 20 child objecs. 2. the host would be new and delete very frequently. 3. all the operations from the child would be invoked like this : pHost->GetA()->DoSomething(),and also very frequently. 4. CHost1 use objects as child,CHost2 use poniter and new child in constructor. my question is: 1. since I would new and delete CHost very ofen,may be in the server loop, is CHost2 a bad design? 2. since all the method of the child would be invoked like this: pHost->GetA()->DoSomething(). is this indirect call cost a lot compare to pHost->DoSomething, because it happens a lot. If CHost2 is a bad design, I would use CHost1 or use CHost2 and a CHost2 Pool. If Indirect call cost a lot.I would only use CHost3 without child objects,and all method would be like pHost->Dosomething Thank you all. ps I can't use the code button to format the code,I tried chrome and ie,why class CHost1 { public: CHost1(){} public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1 m_1; C2 m_2; CN m_n; }; class CHost2 { public: CHost2() { m_p1 = new C1; m_p2 = new C2; m_pN = new CN; } public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1* m_p1; C2* m_p2; CN* m_pN; };
-
I'm working on a GAME SERVER program. there is a design problem confused me. Basic Situation: 1. the host object just as bellow has a lot of child objects. eg, 20 child objecs. 2. the host would be new and delete very frequently. 3. all the operations from the child would be invoked like this : pHost->GetA()->DoSomething(),and also very frequently. 4. CHost1 use objects as child,CHost2 use poniter and new child in constructor. my question is: 1. since I would new and delete CHost very ofen,may be in the server loop, is CHost2 a bad design? 2. since all the method of the child would be invoked like this: pHost->GetA()->DoSomething(). is this indirect call cost a lot compare to pHost->DoSomething, because it happens a lot. If CHost2 is a bad design, I would use CHost1 or use CHost2 and a CHost2 Pool. If Indirect call cost a lot.I would only use CHost3 without child objects,and all method would be like pHost->Dosomething Thank you all. ps I can't use the code button to format the code,I tried chrome and ie,why class CHost1 { public: CHost1(){} public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1 m_1; C2 m_2; CN m_n; }; class CHost2 { public: CHost2() { m_p1 = new C1; m_p2 = new C2; m_pN = new CN; } public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1* m_p1; C2* m_p2; CN* m_pN; };
Allocating class members on the heap is not per se bad design. It avoids for example stack overflows when the class is created on the stack and the members use a lot of memory. But allocating and freeing memory frequently reduces the performance significantly. So the Host2 option seems to be the best option for you. If the members use so much memory that stack overflows might occur, create Host2 always on the heap using
new
. The indirections should not be a problem. The overhead is very small compared to heap allocation. Some indirections may be also removed by the compiler. And you might not be able to remove them because with your example I did not see a chance to do that:// Assuming
CHost::GetA() { return &m_A; }
CA::DoSomething { /* body */ }
// then
pHost->GetA()->DoSomething();
// is effectively
pHost->&m_A->DoSomething();
// or
pHost->m_A.DoSomething();// Can be also implemented as
CHost::DoSomethingWithA() { m_A.DoSomething(); }
// which is effectively called as
pHost->m_A.DoSomething();As you can see both methods are not really different.
-
I'm working on a GAME SERVER program. there is a design problem confused me. Basic Situation: 1. the host object just as bellow has a lot of child objects. eg, 20 child objecs. 2. the host would be new and delete very frequently. 3. all the operations from the child would be invoked like this : pHost->GetA()->DoSomething(),and also very frequently. 4. CHost1 use objects as child,CHost2 use poniter and new child in constructor. my question is: 1. since I would new and delete CHost very ofen,may be in the server loop, is CHost2 a bad design? 2. since all the method of the child would be invoked like this: pHost->GetA()->DoSomething(). is this indirect call cost a lot compare to pHost->DoSomething, because it happens a lot. If CHost2 is a bad design, I would use CHost1 or use CHost2 and a CHost2 Pool. If Indirect call cost a lot.I would only use CHost3 without child objects,and all method would be like pHost->Dosomething Thank you all. ps I can't use the code button to format the code,I tried chrome and ie,why class CHost1 { public: CHost1(){} public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1 m_1; C2 m_2; CN m_n; }; class CHost2 { public: CHost2() { m_p1 = new C1; m_p2 = new C2; m_pN = new CN; } public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1* m_p1; C2* m_p2; CN* m_pN; };
It is actually the situation where you use a delegate. It is very common on game servers which are doing things like guns/projectiles etc to do this. The reason is you want to bind a behaviour to a random class without worrying what the class is and going thru the issue you have. So when I have a bullet I don't care if it's a 50 cal, 45 magnum or a BB pellet it has a behaviour and I will execute the delegate function to move it and use the payload to hold a callback for the object to draw itself and vary the damage etc. The classes don't even have to be related to use a delegate they can have random relationships and it's safe. So unlike a class/object a delegate is an action or an event and generally it carries a payload which can be other actions or objects. You called your function DoSomething and it goes to another object :-) The other cute thing is you can add and delete delegates at any time to an object and you can test for the presence of a delegate. So you can add/delete and turn on/off functionality to a class/object with ease without the class itself needing to know or building that functionality on all related classes. All real game engines do it that way and typically your server connects to players etc via delegates. Usually it is just doing things like scoring etc and removing dead people etc so it doesn't care what the objects are it just needs a couple of things from them. The last thing you want the server doing is get involved heavily in the objects or you will bottleneck everything. When an object disconnects from the server it simply removes itself from the server multicast delegates and the server will no longer see it and it's free to delete itself or whatever in it's own good time. So typically a server doesn't get involved in creating or deleting objects either which is the responsibility of a spawn system(s). Delegates | Unreal Engine[^] Unity - Delegates[^](worth watching the video to see it's use in a game) Unreal Engine has the classical layout (look at the block diagram at bottom) .. GameServer sits alone things only join
-
I'm working on a GAME SERVER program. there is a design problem confused me. Basic Situation: 1. the host object just as bellow has a lot of child objects. eg, 20 child objecs. 2. the host would be new and delete very frequently. 3. all the operations from the child would be invoked like this : pHost->GetA()->DoSomething(),and also very frequently. 4. CHost1 use objects as child,CHost2 use poniter and new child in constructor. my question is: 1. since I would new and delete CHost very ofen,may be in the server loop, is CHost2 a bad design? 2. since all the method of the child would be invoked like this: pHost->GetA()->DoSomething(). is this indirect call cost a lot compare to pHost->DoSomething, because it happens a lot. If CHost2 is a bad design, I would use CHost1 or use CHost2 and a CHost2 Pool. If Indirect call cost a lot.I would only use CHost3 without child objects,and all method would be like pHost->Dosomething Thank you all. ps I can't use the code button to format the code,I tried chrome and ie,why class CHost1 { public: CHost1(){} public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1 m_1; C2 m_2; CN m_n; }; class CHost2 { public: CHost2() { m_p1 = new C1; m_p2 = new C2; m_pN = new CN; } public: C1* Get1(); C2* Get2(); CN* GetN(); private: C1* m_p1; C2* m_p2; CN* m_pN; };