class Singleton
{
public:
void create();
virtual int init() { return 0; }
virtual int shutdown() { return 0; }
protected:
Singleton()
{
init();
}
virtual ~Singleton()
{
shutdown();
}
};
[C++] Inheritance not working from constructor?
Hey all,
I'm having this small problem with my code - I have a base Singleton class (not a complete code listing):
The purpose of this code is, when the Singleton is created, the init() function is called to perform initialization, and when it is destroyed, the shutdown() function is called to perform shutting-down. Classes that inherit from Singleton can override init() and shutdown().
My problem is - I have a derived class that overrides both init() and shutdown(), but when the Singleton is created, the base Singleton's init() function is called instead of the overridden init() function (obviously I want the overridden one to be called).
Not implementing init() and shutdown() in Singleton of course causes the compiler to tell me that, I can't use those functions in the constructor/destructor because they're not defined. Since there's some error-checking code wrapping init() and shutdown() (not shown here), I don't want to copy & paste the constructor code to each derived class.
Can anyone help me get this working? Thanks in advance!
Won't work. C++ (unlike C#) does not apply the "virtual" to functions called in the constructor/destructor for technical reasons.
Hmm. Would it work if I did something like this:
I figure that that might work for construction, but I still dunno about destruction...
Cheers!
// ... void create() { if ( !ms_Singleton ) { ms_Singleton = new T(); // Singleton< T > of course init(); } }
I figure that that might work for construction, but I still dunno about destruction...
Cheers!
Why do you need to do this? What's wrong with just putting the init and shutdown code in the derived class's constructor and destructor? That's what they're for...
The only good reason I can think of is that it allows me to handle errors more effectively. Otherwise, yes I suppose I should be just doing it in the constructor [smile].
Thanks and cheers!
Thanks and cheers!
That will probably work with some small changes:
class Singleton { public: static void create(); ... }; void Singleton::create() { if ( !ms_Singleton ) { ms_Singleton = new T(); // Singleton< T > of course ms_Singleton->init(); } }
create() needs to be static so that you can call it without already having an instance of the class. There is probably no need make shutdown() virtual because with a virtual destructor, all the destructors are called.Quote:Original post by fyhuang
Hey all,
I'm having this small problem with my code - I have a base Singleton class (not a complete code listing):
*** Source Snippet Removed ***
The purpose of this code is, when the Singleton is created, the init() function is called to perform initialization, and when it is destroyed, the shutdown() function is called to perform shutting-down. Classes that inherit from Singleton can override init() and shutdown().
My problem is - I have a derived class that overrides both init() and shutdown(), but when the Singleton is created, the base Singleton's init() function is called instead of the overridden init() function (obviously I want the overridden one to be called).
Not implementing init() and shutdown() in Singleton of course causes the compiler to tell me that, I can't use those functions in the constructor/destructor because they're not defined. Since there's some error-checking code wrapping init() and shutdown() (not shown here), I don't want to copy & paste the constructor code to each derived class.
Can anyone help me get this working? Thanks in advance!
Because in ctor the vtable slots not being completely setup yet,and in dtor,the vtable is restored back...
So,calling of init or shutdown is the CSingleton::init and CSingleton::shutdown,not any inheritance version...
The reason for why this happens is described in detail here along with several possible workarounds (some of which have already been posted).
Quote:Original post by Andrew Russell
The reason for why this happens is described in detail here along with several possible workarounds (some of which have already been posted).
Thanks for that. I picked up a useful peice of know-how from that article I wasn't aware of.
In C++, an object of a derived class is progressively constructed.
Suppose you have class Base and derive from it, class Derived.
C++ first calls Base's constructor. If this contains virtual functions, they are not yet overridden, because at this point, the object is still a "Base" object (in fact, it's not really even that yet, it's partially complete).
Once the "Base" constructor is called, then the Derived constructor is called. At this point, the object has become (a partially constructed) a Derived. Therefore overridden virtual functions called *now*, will call Derived's ones.
If Derived's constructor throws an exception, Base's destructor will be called, but Derived's won't be (as it isn't yet *fully* constructed).
It all makes perfect sense - you *cannot* call a class's methods before its base class has been constructed - as they might in turn call methods of the base class which relied on private members of the base class which weren't assigned their right values yet, which would break (obviously).
(Note that this is different from Java, where you *can* do this, although it still doesn't make very much sense, and some people view it as a bug)
---
You might do better making Singleton a template class rather than a base class for your objects stored in it.
Mark
Suppose you have class Base and derive from it, class Derived.
C++ first calls Base's constructor. If this contains virtual functions, they are not yet overridden, because at this point, the object is still a "Base" object (in fact, it's not really even that yet, it's partially complete).
Once the "Base" constructor is called, then the Derived constructor is called. At this point, the object has become (a partially constructed) a Derived. Therefore overridden virtual functions called *now*, will call Derived's ones.
If Derived's constructor throws an exception, Base's destructor will be called, but Derived's won't be (as it isn't yet *fully* constructed).
It all makes perfect sense - you *cannot* call a class's methods before its base class has been constructed - as they might in turn call methods of the base class which relied on private members of the base class which weren't assigned their right values yet, which would break (obviously).
(Note that this is different from Java, where you *can* do this, although it still doesn't make very much sense, and some people view it as a bug)
---
You might do better making Singleton a template class rather than a base class for your objects stored in it.
Mark
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement