anthnich
|
|
« Reply #20 on: December 03, 2014, 06:30:13 PM » |
|
That's why I'm a fan of the explicit init.
namespace with state would be like
SomeThingThatHasState::Init();
or singleton
SomeThingThatHasState::Init();
I use this as well. I have systems that rely on others, so I need an explicit init/deinit order. These are things I am comfortable micromanaging. Everything else follows standard RAII principles.
|
|
|
Logged
|
|
|
|
Boreal
Level 6
Reinventing the wheel
|
|
« Reply #21 on: December 03, 2014, 09:32:25 PM » |
|
What I do with regards to "singleton resources" such as an OpenGL context is implement them with regular init/free functions internally but expose a class that is a "view" of that resource, with automatic reference counting. It makes sure that if a piece of code can call a function that requires some service to be loaded, the service is guaranteed to be loaded by the compiler. Dependencies can be resolved simply by adding a member variable of the desired service class. For example, my renderer depends on the window.
|
|
|
Logged
|
|
|
|
Branno
TIGBaby
|
|
« Reply #22 on: December 05, 2014, 01:26:40 AM » |
|
I am working on a strategy/roguelike in C++. I have some functions for generating maps (generating random points, voronoi) and other functions that are not dependent on game code. Then of course I have classes like Map, Entity etc.
I haven't used C++ for some time now and I can't decide how to best organize my code. Should I create a namespaces for these functions, e.g. "voronoi" with generate function and other required functions for voronoi algorithm. Another approach would be to create classes with static methods.
What approach do you use in your games? It would be great if you could show some examples.
That! Why creating a class with static methods when you can just open a namespace and put functions into it? It's just like... Why?! Namespaces are the proper C++ solution. Classes with static methods are largely a hack used by languages like Java that don't support free functions.
|
|
|
Logged
|
|
|
|
kamac
|
|
« Reply #23 on: December 05, 2014, 11:20:42 AM » |
|
I, myself, detest the MyNamespace::Init or MyClass::Init. Feels ugly to me. I'd rather use a singleton there, if possible.
|
|
|
Logged
|
|
|
|
oahda
|
|
« Reply #24 on: December 05, 2014, 12:56:27 PM » |
|
I don't really care either way TBH (depending on what the structure is supposed to do). just mak gam
|
|
|
Logged
|
|
|
|
InfiniteStateMachine
|
|
« Reply #25 on: December 05, 2014, 01:20:00 PM » |
|
Yeah ultimately it's not a big issue. Neither of them really hinder your progress.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #26 on: December 05, 2014, 02:51:43 PM » |
|
Yeah ultimately it's not a big issue. Neither of them really hinder your progress.
To me it's a big issue, but I'm a "language guy." Let's just say that if someone brought me C++ code with a singleton when I was doing a job interview, my impression would be that this person doesn't really understand the language.
|
|
|
Logged
|
What would John Carmack do?
|
|
|
InfiniteStateMachine
|
|
« Reply #27 on: December 07, 2014, 08:58:47 PM » |
|
Yeah ultimately it's not a big issue. Neither of them really hinder your progress.
To me it's a big issue, but I'm a "language guy." Let's just say that if someone brought me C++ code with a singleton when I was doing a job interview, my impression would be that this person doesn't really understand the language. I would consider myself a bit of a language guy as well but past experience has yielded people I've met who have a very advanced understanding of the language but still encourage singletons. Whether it be for whiteboxing (members are shown in the header), source merging resistance or otherwise they have generally understood the implications of the design decision they chose to implement. It's often been a very conscious decision. Mind you I generally agree with your perspective, I've just met enough people who have enough knowledge of the language yet still choose that method to the point I avoid prejudice of people using singletons in c++. I'd be disingenuous to not suggest it doesn't set some alarms off though.
|
|
« Last Edit: December 08, 2014, 11:16:09 AM by InfiniteStateMachine »
|
Logged
|
|
|
|
Boreal
Level 6
Reinventing the wheel
|
|
« Reply #28 on: December 08, 2014, 06:10:44 PM » |
|
Singletons do have the advantage of their ability to be used polymorphically. But I still think that the way I outlined earlier is better, as on the surface it acts like any other RAII object but with a single, shared resource. What I do with regards to "singleton resources" such as an OpenGL context is implement them with regular init/free functions internally but expose a class that is a "view" of that resource, with automatic reference counting. It makes sure that if a piece of code can call a function that requires some service to be loaded, the service is guaranteed to be loaded by the compiler. Dependencies can be resolved simply by adding a member variable of the desired service class. For example, my renderer depends on the window.
|
|
|
Logged
|
|
|
|
InfiniteStateMachine
|
|
« Reply #29 on: December 09, 2014, 10:55:44 AM » |
|
I've heard that as an advantage but I've never really found a reason to use them polymorphically. I usually just define a interface in my namespace then swap out the cpp per platform with the build system I'm using. Unless maybe I don't have a build script setup but I usually do if I'm targetting more than one platform.
I suppose that's the same thing again. Different ways of achieving similar results that both work.
|
|
|
Logged
|
|
|
|
Cheesegrater
Level 1
|
|
« Reply #30 on: December 09, 2014, 11:21:10 AM » |
|
It's nice if you need to handle the switch at runtime - I support (under duress!) an application that does this and some dynamic loading/unloading of dlls to switch graphics engines between windows GDI, OpenGL 1.X, 2.X, and DirectX.
|
|
|
Logged
|
|
|
|
Boreal
Level 6
Reinventing the wheel
|
|
« Reply #31 on: December 09, 2014, 01:04:16 PM » |
|
I've heard that as an advantage but I've never really found a reason to use them polymorphically. I usually just define a interface in my namespace then swap out the cpp per platform with the build system I'm using. Unless maybe I don't have a build script setup but I usually do if I'm targetting more than one platform.
I suppose that's the same thing again. Different ways of achieving similar results that both work.
This is what I do with regards to cross-platform issues. But (even if it's not really necessary) I like to build systems on top of guarantees, and thanks to RAII either the resource is loaded when a method can be called or an exception has been thrown and the reference is inaccessible anyways. There's still the issue of new/delete when it comes to those objects but you aren't getting any sympathy from me if you break my API and it, well, breaks.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #32 on: December 09, 2014, 04:29:33 PM » |
|
The thing for me is that a class is a data type. If your class can only support a single instance, it's not a data type, it's just data. You're using the wrong tool for the job.
It's akin to using a goto and a label instead of a while loop. Does it work? Sure, but the language provides you with better options.
Even if people insist on making these things classes (which I think is indicative of insane OOP indoctrination) make them proper classes that can support multiple instances, be copied/moved etc...
|
|
|
Logged
|
What would John Carmack do?
|
|
|
Boreal
Level 6
Reinventing the wheel
|
|
« Reply #33 on: December 09, 2014, 05:27:05 PM » |
|
Here's a simple example of what I mean. Doesn't include exception handling but it's not hard to figure out how it would work. http://pastebin.com/Kzdwukzn
|
|
|
Logged
|
|
|
|
InfiniteStateMachine
|
|
« Reply #34 on: December 10, 2014, 10:51:21 AM » |
|
Even if people insist on making these things classes (which I think is indicative of insane OOP indoctrination) make them proper classes that can support multiple instances, be copied/moved etc...
The part I bolded is probably what makes me worried the most when I see a lot of singletons in c++ code. I have to ask whether or not they did it consciously or if they are falling back on some bad habits they learned in an overly OOP focused post-secondary education. As for the proper classes comment. Usually I've seen this implemented as subsystems that actually do need to be single instances of data. Now I know this point this would lead a full circle back to the namespaces argument. On that front I'm not going to argue too hard in favor of the singleton because I can only be the devils advocate to a certain degree. I'm just not willing to totally dismiss someones understanding of the language based on that one issue.
|
|
|
Logged
|
|
|
|
InfiniteStateMachine
|
|
« Reply #35 on: December 11, 2014, 09:25:06 AM » |
|
Here's a simple example of what I mean. Doesn't include exception handling but it's not hard to figure out how it would work. http://pastebin.com/Kzdwukznwouldnt that cause the system to get init and de-init if you bounce back and forth a lot between 1 and 0? Typically when I'm designing these kinds of systems I want them inited and de-inited once.
|
|
|
Logged
|
|
|
|
Average Software
|
|
« Reply #36 on: December 11, 2014, 04:38:10 PM » |
|
Here's a simple example of what I mean. Doesn't include exception handling but it's not hard to figure out how it would work. http://pastebin.com/Kzdwukznwouldnt that cause the system to get init and de-init if you bounce back and forth a lot between 1 and 0? Typically when I'm designing these kinds of systems I want them inited and de-inited once. The lack of a copy constructor is also a huge hole in the reference counting scheme. int Service::s_count = 0; // this is BS by the way C++ Don't blame C++, blame the hackjob of a compilation model it inherited from C. There are very good reasons for having to do that.
|
|
|
Logged
|
What would John Carmack do?
|
|
|
Boreal
Level 6
Reinventing the wheel
|
|
« Reply #37 on: December 13, 2014, 04:38:01 AM » |
|
Here's a simple example of what I mean. Doesn't include exception handling but it's not hard to figure out how it would work. http://pastebin.com/Kzdwukznwouldnt that cause the system to get init and de-init if you bounce back and forth a lot between 1 and 0? Typically when I'm designing these kinds of systems I want them inited and de-inited once. In practice that doesn't happen.
|
|
|
Logged
|
|
|
|
|