954,496 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Static member initialization for a privately declared class.

Hello,

I am using a singleton pattern, which works fine. But when I decided to have a singleton of a nested class that is privately declared.

class A : public CSingletonTmpl<A>
{
	class B : public CSingletonTmpl<B>
	{
	};
};
A* CSingletonTmpl<A>::s_Singleton = NULL;
A::B* CSingletonTmpl<A::B>::s_Singleton = NULL;

The last line causes a compile time error: 'A::B' : cannot access private class declared in class 'A'.

I understand that class B is private and if I do not want to make it public, what are my options?

I do know that if I do not use CSingletonTmpl, but declare s_Singleton directly as a member of B, then A::B::s_Singleton can be instantiated. This seems strange to me. Why should not I be able to access s_Singleton if it is in the publicly derived class for B?

Thanks.

sjcomp
Light Poster
33 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

Hello,

I am using a singleton pattern, which works fine. But when I decided to have a singleton of a nested class that is privately declared.

class A : public CSingletonTmpl<A>
{
	class B : public CSingletonTmpl<B>
	{
	};
};
A* CSingletonTmpl<A>::s_Singleton = NULL;
A::B* CSingletonTmpl<A::B>::s_Singleton = NULL;

The last line causes a compile time error: 'A::B' : cannot access private class declared in class 'A'.

I understand that class B is private and if I do not want to make it public, what are my options?

I do know that if I do not use CSingletonTmpl, but declare s_Singleton directly as a member of B, then A::B::s_Singleton can be instantiated. This seems strange to me. Why should not I be able to access s_Singleton if it is in the publicly derived class for B?

Thanks.


please post your singleton implementation

mattjbond
Junior Poster
149 posts since Mar 2010
Reputation Points: 66
Solved Threads: 21
 
please post your singleton implementation


Here it is:

#include <boost/noncopyable.hpp>
template<typename T> class CSingletonTmpl : private boost::noncopyable
{
protected:
	/// Pointer to the singleton object
	static T* s_Singleton;
	/// Constructor
	CSingletonTmpl( void )
	{
		assert( !s_Singleton && "Singleton is already initialized, only one initialization is allowed");
#if defined( _MSC_VER ) && _MSC_VER < 1200	 
		int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;
		s_Singleton = (T*)((int)this + offset);
#else
		s_Singleton = static_cast< T* >( this );
#endif
	}
public:
	/// Destructor
	virtual ~CSingletonTmpl(void)
	{
		s_Singleton = 0;
	}
	/// Returns reference to the singleton object
	static T& GetSingleton(void)
	{
		assert(s_Singleton && "Singleton should be created before it can be accessed");
		return(*s_Singleton);
	}
	/// Returns pointer to the singleton object
	static T* GetSingletonPtr(void){return s_Singleton;}
};
sjcomp
Light Poster
33 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

I don't know anything about a "singleton pattern" but my guess is this is one part of your problem:

protected:
	/// Pointer to the singleton object
	static T* s_Singleton;


While a protected status is less-restrictive than private. It simply means that inherited objects can now have access to it, but external code (which yours appears to be) still can not.

There seems to be another issue, but I can't put my finger on what it is.... Something isn't reading right to me... It may just be my naivety RE: singleton pattern...

[edit] This link may help...IDK... It seems to suggest using a static function to return a reference to the static object as part of the initialization.

Fbody
Posting Maven
2,930 posts since Oct 2009
Reputation Points: 833
Solved Threads: 393
 

I don't know anything about a "singleton pattern" but my guess is this is your problem:

protected:
	/// Pointer to the singleton object
	static T* s_Singleton;

While a protected status is less-restrictive than private. It simply means that inherited objects can now have access to it, but external code (which yours appears to be) still can not.


I would agree with you, but the compiler complains about A::B and not about A::B::s_Singleton, which implies that it does not even go all the way there. But to test it, I made s_Singleton public and it did not change the error.

sjcomp
Light Poster
33 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

After thinking a little more I realized that the problem must be with this statement:

CSingletonTmpl<A::B>


. A::B can not be accessed by anything other than A. But if I use

friend CSingletonTmpl<B>;


after B declaration, then the code compiles just fine. Any suggestions on why this may not be a good practice?

sjcomp
Light Poster
33 posts since Feb 2008
Reputation Points: 10
Solved Threads: 0
 

IDK why, but I didn't see your last 2 posts, I don't think my browser was refreshing correctly. I added a link to my previous post that may be useful.

I've only read about friends, I really know nothing about them... I do know that you need to use them sparingly. The link I provided does not mention anything about them...

Fbody
Posting Maven
2,930 posts since Oct 2009
Reputation Points: 833
Solved Threads: 393
 

With template code you have to be careful on relying on the compiler. You can have broken code that the compiler does not complain about. Until you instantiate a class you cannot be sure that you have no conflicts.

Your singleton method seems a little unusual to me it may have something to do with the boost library with which I am not familiar.

If you use a static factory method it does not matter if the constructor is called more than once, this is why it is declared private/ protected. Otherwise you can have just a static int check > 0

//singleton factory method
class highlander
{
public:
//factory method get the one and only 
static highlander * create()
{
 if(pointer == 0)
 {
  //may want try catch to ensure new doesn't fail
   pointer = new highlander();
 }
return pointer;
}
private:
highlander() {//does nothing}

static highlander * pointer;
}


there are several singleton approaches and it depends on what you want
a single global
avoiding duplicates
just one at one time
one per template

But templating singleton there are several problems that might be created, your constructor looks odd to me as you are casting
this to T* but this does not inherit from T with singleton it is important to know what you are using it for.

Template classes are tricky to use with inheritence and you should only use them when you are sure that they are needed as there will normally be several design options and I have found that static template and virtual often play badly together.After thinking a little more I realized that the problem must be with this statement:

CSingletonTmpl<A::B>


. A::B can not be accessed by anything other than A. But if I use

friend CSingletonTmpl<B>;


after B declaration, then the code compiles just fine. Any suggestions on why this may not be a good practice?

tetron
Junior Poster
199 posts since Feb 2010
Reputation Points: 32
Solved Threads: 37
 

Line 8 should be:

A::B* A::B::CSingletonTmpl<B>::s_Singleton = NULL;

which reflects the type of the singleton pointer, and the access required to reach it through A, B, and CSingletonTmpl, I think.

madGambol
Newbie Poster
1 post since Nov 2011
Reputation Points: 10
Solved Threads: 0
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: