Looking for design clarification.

In my program I have a class (M) that is needed by very basic parts of a system - I only need one instance of M.
Other systems may need to have access to M and these other systems are within other systems.

For illustration:
1
2
3
4
5
6
7
8
9
10
11
12
Class A3a requires access to M.

M (class that class A3a requires)

A (class)
	A1 (class within A)
	A2
	A3
		A3a (class within A3)
		..
	..
..


My solution to this issue was to create a singleton and now I have a lot of singletons (such as one for sound, graphics, networking, etc). Is this proper? It feels strange that I'm using these singletons all over the place.

Another problem was that classes that needed a singleton accessed it often enough to justify creating a static pointer within that class to that singleton. The issue here is that the only proper way to initialize it was to use a static function to do so. Leading to a large number of classes having static initializing functions.

A way I used to get around that was to create a class with a static pointer to a singleton, which is only initialized once. And then inherit from that class - which now means that class has access to that static init. However, this leads to multiple inheritance, which I've heard is not a good thing to have. What are your suggestions?

Illustration:
1
2
3
4
5
6
7
8
9
10
11
12
13
class B{
public:
	static void Init( M ){ Maccessor = M; }
private:
	static M *Maccessor;
};

class A3a{
public:
	static void Init( M ){ Maccessor = M; }
private:
	static M *Maccessor;
};


To

1
2
3
4
5
6
7
8
class MBase{
public: 	static void Init( M ){ Maccessor = M; }
protected:	static M *MAccessor;
};

class B : public MBase{...};

class A3a : public MBase{...};

Last edited on
The inheritance method is not the way to go, but not necessarily because of multiple inheritance -- it's just not
intuitive to me. (Multiple inheritance does have its good uses, but that is a topic for another thread).

I think you are saying that the justification for making static pointers in your classes is so that you can shorten
the lines of code that require the pointer? ie,

Sound::GetInstance()->Play( "bing.wav" );

vs.

pSound->Play( "bing.wav" );

?

If so, why not have a helper function in the sound module?

1
2
3
4
5
6
7
8
9
10
11
12
13
class Sound {
    public:
         static Sound& GetInstance() {
             static Sound sound;
             return sound;
          }

    // other stuff
};

inline Sound& sound() {
    return Sound::GetInstance();
}


There will be no overhead for the extra function call since it is inline.
K I think I'll try that, would it be weird to make it a template?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class A>
class InstanceTemplate
{
public:
	static A &GetInstance(){
		static A a;
		return a;
	}
};


class Sound : public InstanceTemplate<Sound>
{};
Yes that would be weird, because it would need to be instantiated in every cpp file otherwise you might get multiple objects.*


*AFAIK
It's not a problem in this limited case, however the full-blown singleton pattern
is surprisingly difficult to design and implement in a generic fashion (otherwise
boost, for example, would definitely provide one).
Disch
Do you mean the same sort of error produced when leaving out #pragma once / #ifndef #endif in the .h when trying to declare a class?

I haven't found any issues while testing the InstanceTemplate but maybe my tests aren't hardcore enough.

Could someone provide an example that would produce an error using the InstanceTemplate?

jsmith
I guess I'm lucky only dealing with my example of code which I know how I'll use down the road. I can see how the template may not be suitable for others.

I'm just wondering for this specific case, with a project of some complexity, would using this sort of design cripple me into a coding mess?
Last edited on
Could someone provide an example that would produce an error using the InstanceTemplate?


It's not that it would produce an error, it's that it would no longer be a singleton.

Although now that I look closer at your example... you're probably okay if you derive from that class, rather than use it directly.

This is what I was thinking:

1
2
3
4
5
6
7
8
9
10
11
// in a header

template <class A>
class InstanceTemplate
{
public:
	static A &GetInstance(){
		static A a;
		return a;
	}
};

1
2
3
4
5
6
// in a.cpp

void A()
{
  Sound& snd = InstanceTemplate<Sound>::GetInstance();
}

1
2
3
4
5
6
7
8
// in b.cpp

void B()
{
  Sound& snd = InstanceTemplate<Sound>::GetInstance();
  // SURPRISE 'snd' isn't the same object as in a.cpp because the template is instantiated
  // seperately in each cpp file.
}



HOWEVER, like I said if you derive from the class then the Sound class instantiates InstanceTemplate<Sound> so you're probably okay.
Last edited on
Ok, I see.
Thanks for your time disch!

I'm just wondering for this specific case, with a project of some complexity, would using this sort of design cripple me into a coding mess?


Just off the cuff, one of the limitations of the template-based solution is it only supports default
construction of the singleton. But otherwise, no, the only external interface you have into the
"singleton stuff" is the GetInstance() method, and that will not change regardless of the design.

It's just I'm not sure the problem is solvable generically, which implies that the template-based
solution may not be useful across the board. (Prefer one solution to a problem than N).
Topic archived. No new replies allowed.