I need to be able to create one instance of a class, and when I tried to create two or more instances, an error fell out! How to implement it?

    5 answers 5

    formally, you need a singleton , just a bit distorted.

    See how it is implemented and you can do what you want.

      Use a static variable in the constructor under the counter

      • The same Singleton. The same crayfish, only speckled :) - mega
      • Suppose one instance is created (static bool alreadyCreated = true), then an attempt is made to create a second instance, then how in the class itself to block this feature? - rejie
      • Suppose it is not a constructor, but a new operator. - mega
      • @mega let's say as an option! And how does this answer my question? - rejie 2:44
      • > And how does this answer my question? void * MyClass :: operator new (size_t size) {static bool alreadyCreated = false; if (alreadyCreated) {return NULL; } alreadyCreated = true; return :: operator new (size); } In the constructor, about the same thing, only instead of NULL we throw a thread of exception: MyClass :: MyClass (void) {static bool alreadyCreated = false; if (alreadyCreated) {throw "already exists !!!"; } alreadyCreated = true; ...} - mega Nov.

      Make the constructor private, letting the creation of instances be available only through the factory. Cancel the default copy constructor and assignment statement. All logic can be implemented in a factory. Watch your streams - what happens if two threads at the same time want to create the first instance?

      Pseudocode:

       class Target : Noncopyable // Noncopyable отменяет assignment/copyctor { friend class TargetFactory; private: Target() {} }; class TargetFactory { static bool alreadyCreated = false; static mutex mutex; static Target* Create() { lock(mutex) { if (alreadyCreated) throw ConstraintViolation(); alreadyCreated = true; return new Target(); } } }; 
      • I currently do not use multi-threading, thanks for the example! - rejie
      • If it's not a secret what is a factory ?! - rejie
      • @rejie: ​​well, this is somewhere that in my example TargetFactory : the thing that creates instances of another class. In general, here , here and here . - VladD 2:43

      Thanks for the tip! From Wikipedia:

      A possible implementation in C ++ (known as the Myers singleton), where the loner is a static local object. The important point is that the class constructor is declared as private, which allows you to prevent the creation of instances of the class outside of its implementation. In addition, the copy constructor and the assignment operator are also declared closed. The latter should be determined, since this allows, in the case of a random call from the code, to obtain an easily detectable layout error. Note also that this example is not thread-safe in C ++ 03; to work with a class from several threads, you need to protect theSingleInstance variable from simultaneous access, for example, using a mutex or critical section. However, in C ++ 11, Myers' singleton is thread-safe and without any locks.

        In the first case, I probably got excited: if the new operator returns NULL , an exception may occur (although not necessarily, did not check), but the second one should be working:

         try{ MyClass*a = new MyClass; } catch( const char*pszMessage ){ // уже существует } 

        And how is it for the end user to make the exception handling procedure for this class "invisible", that is, that there would be no need to include in the try code?

        @rejie , and how were you going to control the processing of the case when an attempt is made to create a second instance of the class? I think you need to first think about this issue.

        If the end user needs a pointer to an object, then simply write a function that wraps the creation of the class into try-catch .

        If the end user needs an object "on the stack", then exception handling cannot be done, unless the end user himself checks the object counter.

        ps: comments are over, I had to highlight the answer.

        • Probably it makes sense to tell why this is all I need? I can not decide where to go next! There is a third-party API in the form of a dll written in C. It contains both normal functions and callback functions (the API interacts with some application). Once I use C ++ it would be more logical to encapsulate the whole thing into a class. - rejie
        • As I understood, using CallBack. Functions inside the class will not work because of the need to use Extern "C". It is necessary to call CallBack in time, from the body of CallBack call the corresponding static class function, like crooked !? - rejie
        • On the one hand, the API is initialized once, the CallBack functions are represented by a single instance, on the other hand, it is appropriate to use several instances of the class to receive and process data. As it is necessary to combine all this into one! The interface to my class should be minimal, understandable for use by third-party developers. Something like this ... - rejie
        • In CallBack'и usually allow you to transfer some AppUserData variable that can be used to store an object, i.e. for example: SomeApiCall (..., Callback, AppUserData); ... INT CALLBACK Callback (..., AppUserData) {...} Here, if AppUserData transfer SomeApiCall object to CallBack'е to this CallBack'е you can transfer control to this object in CallBack'е itself: MyObject Obj = new MyObject (... ); SomeApiCall (..., Callback, (...) Obj); ... INT CALLBACK Callback (..., AppUserData) {return ((MyObject ) AppUserData) -> SomeCallback (...); i.e. control of the number of objects is not needed! - mega
        • To set up CallBack, I need to call a function like SET_CALLBACK (CALLBACK pfConnectionStatusCallback, long * pnExtendedErrorCode, LPSTR lpstrErrorMessage, DWORD dwErrorMessageSize) that is, in principle, what you are saying is not implemented! - rejie