Skip to main content
gamedev.net
🔒 Locked

style:access singleton

Started by Zoomby May 26, 2003 at 3:21 AM 16 replies 1.1k views
Original Post
Zoomby
Zoomby
hi Consider the singleton class below. Is it a good habit/style to use the #define to make the access to the class easier? Are there other possibilities?
  

#define GET (MySingleton::get())

class MySingleton
{
    static MySingleton* m;

    public:
    staticMySingleton* get()
    {
      return m;
    }

    void test() {}

};



int main()
{
       GET->test();         //easy access

}


  
pag
pag
hmm... it''s just a question about style. However my leading star is that whatever you write it should be clear of what you are doing, and that GET isnt.
I am a signature virus. Please add me to your signature so that I may multiply.
Zoomby
Zoomby
The problem is, when you have a singleton that is often used, you always have to write "ClassName::getMethod()" to get the pointer.

bye
chris

P.S. Maybe you think it''s not clear because I use GET as the #define name instead of a descriptive name!?
Bad Monkey
Bad Monkey
You should probably avoid using compiler macros altogether (just use inline functions which can provide the same speed, but with the bonus of type-safety). I would definitely steer clear of the usage you show there... is it really that much of an effort to type the class name?

If you need to make a number of calls to the object within a function, just declare a nice short-named pointer to the singleton class and use that instead of the fully-qualified name each time...

i.e.

MySingleton* handle;

handle = MySingleton::Get();

...

Much better at conveying the meaning of the code... I mean come on man , that macro if just frikkin'' laziness in the extreme
Beer Hunter
Beer Hunter
quote:
Original post by Zoomby
The problem is, when you have a singleton that is often used, you always have to write "ClassName::getMethod()" to get the pointer.
...it''s not much of a problem to store the pointer for several consecutive uses:

MySingleton* t = MySingleton::get();
Pie p = t->aquire("pie");
t->eat(p);
t->worship(p);
Way Walker
Way Walker
quote:
Original post by Bad Monkey
You should probably avoid using compiler macros altogether (just use inline functions which can provide the same speed, but with the bonus of type-safety).



Just to be clear, there''s no issue of type safety in this instance. It''s mostly about clarity here. That being said...

quote:

I would definitely steer clear of the usage you show there... is it really that much of an effort to type the class name?



I completely agree. If you made the macro (or inline function name) clear enough, you''d basically be typing the much feared "MySingleton::get()".

quote:

If you need to make a number of calls to the object within a function, just declare a nice short-named pointer to the singleton class and use that instead of the fully-qualified name each time...

i.e.

MySingleton* handle;

handle = MySingleton::Get();

...

Much better at conveying the meaning of the code... I mean come on man , that macro if just frikkin'' laziness in the extreme


I agree, though I''m not sure I''d even make the variable (that is, assuming Get() is fast). Of course, I like long, descriptive names. I''d rather spend 3 more seconds typing now than spend an hour down the road trying to figure out what the heck is going on. (comments would also work, but naming the variables properly can lessen the need for comments and force you to "maintain" your "comments")
daerid
daerid
I use a macro for singletons like so:


  
class Application : public Singleton< Application >
{
public:
// stuff

};
#define gApplication Application::GetInstance()


which allows me to use it like so:
gApplication.SomeMethod(); 
daerid@gmail.com
daerid
daerid
quote:
Original post by Anonymous Poster
Think of a design that doesn't require singletons and you'll be better off.


How so? Sometimes a Singleton can be the appropriate tool for the job.

I don't want to have to store a reference to the Engine object in every freakin other class I make that needs to access it. And then write appropriate constructors to handle the Engine object, and then make sure I pass the Engine object to every other class that I make an instance of that needs access to the Engine. That's just nuts.

Also, the singleton pattern enforces the design intent on the programmer. When a class is declared singleton, and another programmer comes in and tries to instantiate that class, the compiler ( or run-time, in the example I gave above, but better if it's the compiler ) will tell the programmer that the class is intended to be used as a singleton, and as such only one instance is allowed.

[edited by - daerid on May 26, 2003 10:17:14 PM]
daerid@gmail.com
daerid
daerid
I really don''t see that being realistic in many cases. You made some really good points, and I''ll be thinking about them.

The thing to keep in mind is that a Singleton pattern is a valid tool. Whether or not you find it useful doesn''t negate it''s validity. If you prefer not to use it, then don''t.
daerid@gmail.com
Qw3r7yU10p!
Qw3r7yU10p!
quote:
daerid: I don''t want to have to store a reference to the Engine object in every freakin other class I make that needs to access it.

The problem is once you''ve made the engine a singleton you''ll just let every and any class access it (because they can). You would have a better design if you didn''t use a singleton and actually had to tackle thinking about dependencies, reusability etc.

If you think the only alternative to a singleton is storing a reference to the class in every class that needs to know about it then you have a lot to learn.
Cybrosys
Cybrosys
I''m actually using templated singletons atm because it gives me a much greater module support and easy to access style and it makes it extremely easy to port a module to another project.

This is my singleton class that is extremely stable.

  
template<typename Class>
class CSingleton
{
protected:
static Class* m_pInstance;

public:
static Class* GetInstance()
{
if (!m_pInstance)
m_pInstance = new Class;

return m_pInstance;
}

static void Delete()
{
if (m_pInstance)
{
delete m_pInstance;
m_pInstance = NULL;
}
}
};

template<typename Class>
Class* CSingleton<Class>::m_pInstance = NULL;


So whenever I need to create a templated singleton manager class its just


  
class CSomeManager : public CSingleton<CSomeManager>
{
};

inline CSomeManager* SomeManager()
{
return CSomeManager::GetInstance();
}


I always have Initialise and Uninitialize functions aswel in my manager classes, the only thing the coder needs to do is make sure the delete function is called for every Manager class to ensure that the memory is freed. (I put it at the end of its own Uninitialize function)
Cybrosys
Cybrosys
Of course I do have some rules when using the such as that the class mush be self-sustained meaning that if it needs a variable to work, say HINSTANCE, then I wont be asking for it from another singleton but I'd have it sent as a parameter in the initialize function.

[edited by - Cybrosys on May 27, 2003 9:33:48 PM]
davepermen
davepermen
singletons do have uses, but normally get quite quickly abused by newbies (newbies for singletons!) as global variables. you''re bether off defining a global variable then..:D

with nice code design, dependenties are shrinking, and the need to "access some object from everywhere" gets small. the use of the singleton is not really a use anymore.

you should not have tons of calls to the engine. the engine should run by itself, and automagically handle your world. your objects. your events. without you talking to it.

"take a look around" - limp bizkit
www.google.com
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia
My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.