1

Possible Duplicate:
A Singleton that is not globally accessible

Do you know a good design pattern that would make sure that only one instance of an object is created without making this object global in c++? That's what singleton do but I really need it NOT to be global for code access security reasons.

Thanks for your help!

Community
  • 1
  • 1
koleror
  • 338
  • 1
  • 6
  • 22
  • 2
    The typical singleton pattern encapsulates the singleton object as a private static member of the singleton class and provides an `Instance()` method for access. Is this not sufficient? – Dave Rager Dec 24 '11 at 00:01
  • is it that you only want some classes to be able to retrieve the singleton object? – davogotland Dec 24 '11 at 00:10
  • No, I'm not allowed to use Singleton because with this pattern, the object's instance is global and then accessible everywhere in the program which is not secure. – koleror Dec 24 '11 at 00:11
  • it won't be accessible from anywhere in the program if it's encapsulated and private inside a class, right? of course, anyone can retrieve it, but that can be fixed with the friend-hack mentioned in some of the answers. – davogotland Dec 24 '11 at 00:14
  • @davogotland: yes, if you have a nice way that only one object is allowed to instantiate the object, it would be great I think! I thought about a factory that would give it's instance in the object's constructor parameter but the problem is it's not generic and we can't prevent the user to instantiate another factory... – koleror Dec 24 '11 at 00:15
  • @user455998 i'm sorry, but you are being incoherent. it's as if you haven't tested the singleton pattern. how do you mean "only one object is allowed"? – davogotland Dec 24 '11 at 00:24
  • also, singleton doesn't make an object global, it makes an object **globally accessible**. that's a very big difference. – davogotland Dec 24 '11 at 00:25
  • @davogotland: I don't see the difference, except in wording. – GManNickG Dec 24 '11 at 00:29
  • the difference is that if the object pointer was global, then anyone could change what object was pointed to by this pointer. so then there would be no guarantee that everyone would always get the same object. but since the pointer is hidden away inside a class, access to the actual pointer is forbidden, and only access to the object is granted. now anyone can modify the contents of the object, but the object will always stay the same. it's like santa claus. santa claus brings different things from year to year, and everyone has access to changing what he brings. but no one can replace him ;) – davogotland Dec 24 '11 at 00:34
  • @davogotland: Where did object pointer come from? We were talking about an *object* being global versus being globally accessible. I see nothing about pointers there. – GManNickG Dec 24 '11 at 00:37
  • @GMan well... it was sort of implied, since you started talking about the singleton pattern, which is normally implemented using pointers. – davogotland Dec 24 '11 at 00:43
  • @davogotland: Not really. Even if it were totally obviously we were talking about pointers, using the word "object" would then just mean "the object being pointed at". But this discussion is moot since we'r just arguing semantics. – GManNickG Dec 24 '11 at 00:45
  • how about this then: what if you could make it so that 1) there can only ever be one instance of an object at a time, 2) there is one place in the program where a static pointer keeps hold of this one object, even if no one else is currently pointing to this one object, 3) and that static pointer is not accessible by any one but methods inside the class which the one object is an instance of, 4) and, finally, only objects of one (or some) class(es) can retrieve this one object. would that satisfy your needs? – davogotland Dec 24 '11 at 00:59
  • @Xeo: Wow, I forgot about that question and wrote my answer this time almost identically. Was weird to read thinking, "Wow, this guy thought the same thing I did." – GManNickG Dec 24 '11 at 01:01
  • @GMan: Yeah, but this version is better. :) Exception + local static. – Xeo Dec 24 '11 at 01:10
  • @Xeo: Yup, though going by the last comment on my answer in the other question, it should probably be a class-wide static so it can be set back to `false` in the destructor. – GManNickG Dec 24 '11 at 01:12
  • @GMan: Good point, encapsulating it into a static function should solve that. `static bool& created(){ static bool _created = false; return _created; }`. – Xeo Dec 24 '11 at 01:14
  • @Xeo: Ah, I just made it class-wide again. :) I suppose that could be considered cleaner, though. – GManNickG Dec 24 '11 at 01:23

4 Answers4

2

I think you want something like this (note: copy-pasted from an answer I already wrote and forgot about):

#include <stdexcept>

// inherit from this class (privately) to ensure only
// a single instance of the derived class is created
template <typename D> // CRTP (to give each instantiation its own flag)
class single_instance
{
protected: // protected constructors to ensure this is used as a mixin
    single_instance()
    {
        if (mConstructed)
            throw std::runtime_error("already created");

        mConstructed = true;
    }

    ~single_instance()
    {
        mConstructed = false;
    }

private:
    // private and not defined in order to
    // force the derived class be noncopyable
    single_instance(const single_instance&);
    single_instance& operator=(const single_instance&);

    static bool mConstructed;
};

template <typename T>
bool single_instance<T>::mConstructed = false;

Now you get an exception if the class is constructed more than once:

class my_class : private single_instance<my_class>
{
public:
    // usual interface (nonycopyable)
};

int main()
{
    my_class a; // okay
    my_class b; // exception
}

There's no way to enforce the single-instance policy at compile-time in C++, though.


(Also good on you for noticing that singletons are dumb. Globally accessible and singly-creatable are two different concepts, and should only be combined by coincidence, not by design.)

Community
  • 1
  • 1
GManNickG
  • 494,350
  • 52
  • 494
  • 543
1

You could use a singleton with a typical static Instance() access function, but make this function private. Access is then only granted to another class, by making it a friend classes of the singleton class.

Johannes Gerer
  • 25,508
  • 5
  • 29
  • 35
  • 1
    This is no different from a global with an extra level of indirection (what error do you get when that friend class is created in two different places? None? Then the question is unfulfilled.) – GManNickG Dec 24 '11 at 00:53
  • i think Johannes Gerer is right be cause only members of the friend can access to `instance()` so the access to services provided by the singleton and its data is reserved to friend class functions. i wonder if putting the singleton inside another class can also resolve the problem – Hicham Dec 24 '11 at 00:57
  • @eharvest: Once it's a singleton, it's global forever. There's no way around that (except by an incorrect singleton implementation). And if you're going to try to code around it, why start with a singleton at all? – GManNickG Dec 24 '11 at 01:03
  • @GMan: 1. Singleton == There will only be one instance of that class (I didn't invent that, you should know that). 2. The OP requested code access security: The (unique) singleton object will only be accessible for friend classes. 3. The number of friend class object is not restricted (neither by the question nor by my answer) 4. There is no "inirection" at all involved. – Johannes Gerer Dec 24 '11 at 02:09
  • 1
    @JohannesGerer: Your #1 is incomplete: Singleton == There is a single **global** instance of a class (you should know that). He doesn't want a global. He doesn't want multiple instances of the class to be operating on the same instance underneath, he wants multiple instances to be an *error*. And yes, hiding a global behind a proxy class is, by definition, indirection. – GManNickG Dec 24 '11 at 02:34
0

Make the constructor(s) and assignemnt operator private.

Then make the only function that create the one instance of your class a friend of the class.
Since you are writing the function it is the only one that can create the object (and there will be no others in the application).

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • I know I can easily control the creation of the object but the problem is that once created, as the object is global, it is accessible from the whole program. Am I wrong? If yes, can you give me some pseudo-code that would show me how to do it? Thanks! – koleror Dec 24 '11 at 00:19
  • the single instance is not "global" unless the singleton's class instance method is or a reference to it is. the created singleton is only accessible by code that has a reference to it or is allowed to get a reference to it. a reference to the singleton can be kept private and the method described by Johannes and Loki can ensure you control which code has access to the class/instance method; therefore giving you complete control. – Richard Logwood Dec 24 '11 at 00:27
0

you could control the visibility to your singleton class/instance method use a namespace and/or nested and local classes

singleton tutorial http://www.yolinux.com/TUTORIALS/C++Singleton.html

local class example http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=191

Richard Logwood
  • 3,163
  • 23
  • 19