L B wrote: |
---|
You have coupling, which is just as bad as globals. What is worse is that the coupling is completely not obvious to someone using the classes. |
Not really, see the code where it says // evaluates to false. If the items are not present, it'll create them themselves, in this situation, we simply know that the items will always be present.
L B wrote: |
---|
Why is the entire program not thread 2? I don't understand the purpose of creating a separate thread only to have the first thread wait for it to complete. |
I considered that a while ago, but it's not feasible:
If I were to go directly into Class1, Class1 builds Class2, Class1 returns, then the main function returns. What happens when the main function returns (for me) is that the entire program exits abruptly.
L B wrote: |
---|
Why are "this" and "that" not passed as parameters to the constructor? |
They're supposed to be fetched from the hash table so that any class may summon this class, when the items are not present, it initializes them by itself.
L B wrote: |
---|
This has the same effect as returning to main from a function call to draw the menu, and having main then call a function to draw the game. There is no reason to waste resources on creating and destroying threads or transmitting data through a hash table.
|
That's true, but I wouldn't call it a waste just yet.
L B wrote: |
---|
Here's my version:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#include "Menu.hpp"
#include "Game.hpp"
int main(int argc, char **argv)
{
Resource r = getResource();
UserAction ua = UserAction::Menu; //an enum
while(ua != UserAction::Exit)
{
switch(ua)
{
case UserAction::Menu:
{
Menu m (r); //r passed by reference
ua = m.BlockUntilSelect();
} break;
case UserAction::Game:
{
Game g (r); //r passed by reference
ua = g.BlockPlay();
} break;
}
}
return 0;
}
|
Done. |
That's actually perfectly acceptable to me, but I'm being the perfectionist in making it possible to easily scale the code into any proportion. I can for example create virtually endlessly many "chains" of objects acting independently of others.
I do feel that using enums in a switch-case statement, and passing a resource (struct?) is quite good, I've actually done that before and I didn't like it because of the Resource struct gets too tangled with all kinds of information, after a while it's just
like a global since you pass it to every instance explicitly. The case is also true for me, but I am at least able to create a new chain with a clean Resource struct on demand, not by coding it explicitly. I like such generic solution. I also do not send it explicitly, the created object just knows it exists, and it try to get its hands on data if available, else it'll create it by itself.
What I'm very uncomfortable with is the fact that you'd need to add an entry manually in the enum list for every new UserAction, whilst also being forced to add a case for every UserAction in the switch scope. My library automates that. I really dislike programming where for every time I create something, I need to add it to a list, add an entry here, another there... Maybe it comes down to personal tastes but I hope you at least get my point. I've spent quite a lot of time on design, and I've gone through most - if not all - possible solutions, your code being one of them.