singleton

which would you prefer and why?
A class with all static members(data and function) or
a singleton class.
ex class with all static members
1
2
3
4
5
6
7
class rs
{
static bool stat;
public:
static void markUp() { stat=true;}
static void markDown() { stat=false;}
};

or singleton class
1
2
3
4
5
6
7
8
9
10
11
12
class rs
{
bool stat;
public:
void markUp() { stat=true;}
void markDown() { stat=false;}
static rs& getInstance()
{
static rs obj;
return obj;
}
};

Your suggestions are not singletons.
Because in both cases you can create a few instances of your presented class.

The main conception of singleton is one instance of a class, and user of singleton doesn't have possibility to create another one.
afaik his implementation does not allowe the user to create another one, since the constructor is private by default... and he cant access the getInstance()^^...

or am i mistaken, or what do you exactly mean, denis?...
Last edited on
First, let me talk about the "single" in singleton: Always ask yourself under which scope something is "single". Do you want it really be only once per *running process*? This will severly harm the testability of your code. Most of the time, the "single" means "only once from your current application domain", but you wouldn't care, for example, if your main-method gets run twice magically, then you also create two instances..

For example, this is true for most things like "database connection", "logger", "output console" etc.. You don't care whether they are really unique in your *system process*, but whether they are unique in your *current application*. If it happens to share a process with another instance of your application - fine. (Because that's true for most unit test cases).

There are numerous articles about this and my feeling is that the community learnt a lot since the GoF book about why singletons are dangerous and what you can do wrong with them. For this, try to avoid simple static-singleton concepts. My recommendation is: Always strive for the "least singleton possible".

(Obviously, there are singletons that make sense in a "single process" - way. E.g. getting your process handle, setting your process priority... ;-)


If "single to the application" is enough, don't go for "single to the whole process". (Remark: There are cases where you want singletons span more than one process. You know if you end up writing Process-Mutexes or network-locks.. ;) )


Now, your question about "static methods" vs "static instance" gets a bit easier to answer. A static instance of one class is the right step towards a "singleton that is actually single only to your application". I'd prefer the second version. It makes it easier later, to e.g. inject a fake-object when you are testing your code from unit tests.

Watch this for a good summary, if you want more on this topic: http://www.youtube.com/watch?v=-FRm3VPhseI


Ciao, Imi.
Edit: Oh, and Denis is right. The constructor is not private by default. You should declare an empty constructor in the private: section of your class.
Last edited on
but can i create two instanace using this method ...like
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class rs
{
     bool stat;
public:
              void markUp() { stat=true;}
              void markDown() { stat=false;}
              static rs& getInstance()
             {
                    static rs obj;
                    return obj;
              }
};
int main()
{
       rs robj1 = rs::getInstance();
       rs robj2 = rs::getInstance();

}


is this right . and if i can create the two instance like this than why is it called singleton class .
All constructors and the assignment operator must be declared private in order to be a singleton,
and in that case, lines 15 and 16 would be compile errors.
A class with all static attributes and functions is not good for much. You can never inherit from it since static functions cannot be virtual. In that case the class is essentially a namespace since no object would ever need to be created. Also you cannot really call that a singleton because you can create hundreds of objects of that type. At least with the second method you leave yourself some future options where you can refactor the implementation. Also the second example is not a singleton either since you did not declare the constructor, copy constructor, or assignment operator.
A class with all static attributes and functions is not good for much.


I actually use a class like this in one of my current projects. But all of the members are private, with friend classes.

Basically it's like a utility class that I want hidden from the end user. For that purpose, it works quite well.

Though I agree if the members are public there's not much point to an all-static class.
I actually use a class like this in one of my current projects. But all of the members are private, with friend classes.

Basically it's like a utility class that I want hidden from the end user. For that purpose, it works quite well.

Though I agree if the members are public there's not much point to an all-static class.


Still, why don't you just change "class" into "namespace" and be more flexible this way (e.g. can spread over multiple headers, can use "using").

Or is it "just for no reason"?


The only reason to prefer "classes with static members" to "namespace" is - again - templates, but I doubt that's the reason for your utility class (especially as you can't template friends). ;-)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct foo
{
    static void fn1();
    static void fn2();
    static void fn3();
};
namespace foo_ns
{
    void fn1();
    void fn2();
    void fn3();
}

template<typename T> struct SomeTemplate
{
    void exec() { T::fn1(); } // works only for T = foo. There is no such thing as T = foo_ns
};


Ciao, Imi.

Edit: Ah, I'm sorry. I should have thought more about it. Of course, it is *exactly* because you can't make functions in namespaces private at all, right? Well, I'd say: just don't ship the header then! ;-). But your solution got a point, yes.. Interesting..
Last edited on
Topic archived. No new replies allowed.