开发者

Achieving C# "readonly" behavior in C++

开发者 https://www.devze.com 2023-01-02 22:16 出处:网络
this is my first question on stack overflow, so be gentle. Let me first explain the exact behavior I would like to see. If you are familiar with C# then you know that declaring a variable as \"readon

this is my first question on stack overflow, so be gentle.

Let me first explain the exact behavior I would like to see. If you are familiar with C# then you know that declaring a variable as "readonly" allows a programmer to assign some value to that variable exactly once. Further attempts to modify the variable will result in an error.

What I am after: I want to make sure that any and all single-ton classes I define can be predictably instantiated exactly once in my program (more details at the bottom).

My approach to realizing my goal is to use extern to declare a global reference to the single-ton (which I will later instantiate at a time I choose. What I have sort of looks like this,

namespace Global
{
    extern Singleton& mainInstance; // not defined yet, but it will be later!
}

int main()
{
    // now that the program has started, go ahead and create the singleton object
    Singleton& Global::mainInstance = Singleton::GetInstance(); // invalid use of qualified name
    Global::mainInstance = Singleton::GetInstance(); // doesn't work either :( 
}

class Singleton
{
    /* Some details ommited */

    public:
        Singleton& GetInstance()
        {
            static Singleton instance; // exists once for the whole program
            return instance;
        }
}

However this does not really work, and I don't know where to go from here.

Some details about what I'm up against:

I'm concerned about threading as I am working on code that will deal with game logic while communicating with several third-party processes and other processes I will create. Eventually I would have to implement some kind of synchronization so multiple threads could access the information in the Singleton class without worry. Because I don't know what kinds of optimizations I might like to do, or exactly what threading entails (never done a real project using it), I was thinking that being able to predictably control when Singletons were instantiated would be a Good Thing.

Imagine if Process A creates Process B, where B contains several Singletons distributed against multiple files and/or libraries. It could be a real nightmare if I can not reliably ensure the order these singleton objects are instantiated (because they could depend on each other, and calling methods on a NULL object is generally a Bad Thing).

If I were in C# I would just use the readonly keyword, but is there any way I can implement this (compiler supported) behavior in C++? Is this even a good idea? Thanks for any feedback.


Edit

If I was locked in to following the code example above, the selected answer would be the easiest way to do what I needed. I decided to change the pattern away from singleton though, even though I only plan to ever make one of these EntryPoint objects.

class EntryPoint
{

    /* Intentionally defined this way to discourage creation */
    EntryPoint(const EntryPoint &); // undefined & private
    EntryPoint& operator=(const EntryPoint &); // undefined & private

    // public
    EntryPoi开发者_运维问答nt()
    {
        /* All of the action is performed here! */
    }

    /* Other supporting functions */
}

// The easier to understand main function!
int main()
{
    EntryPoint * ep = new EntryPoint(); // transfer control to the entrypoint
    delete ep;
}

One of the reasons I was thinking I would need all these singletons is I plan to create a larger architecture that would support modular plugin-type applications. I also wanted more error-checking and memory protection to minimize memory leaks. I was happy to find that the cross-platform Qt (http://qt.nokia.com/) offers a guarded pointer and other cool features.


Why not just use Singleton::GetInstance directly? Why do you need to store it in a (readonly) global? This solves dependency issues as well.


Only allow access by calling:

Singleton::GetInstance 

Enforce this by making your copy and assignment constructors private

private:
   Singleton(){}
   Singleton(Singleton const&){}; //copy ctor private
   Singleton& operator=(Singleton const&){}; 
0

精彩评论

暂无评论...
验证码 换一张
取 消