I have a class hierarchy which inherits QObject.
I need to perform some operations after construction (when the object is fully constructed) and before destruction (when the object is still complete).
The construction part is no problem, since I can control the construction of an object, making private its constructor and just making public the creator function which already can perform all the required operations.
The problem comes with the destructor. I have done more or less the same: hiding the destructor and providing a destroyer function which performs all the operations and then destroys the object.
Here is where the problem begins:my class hierarchy is used as part of the QJSEngine scripting module, which takes ownership of all the objects, and when it is time, it destroys them using the QObject's destructor, thus, bypassing my destroyer function. It is of no help declaring my destructors private, since the QJSEngine can always execute the QObject's destructor (and by the way, also can any piece of code which casts my pointers to QObject).
I require to perform this operations before calling the destructor, since I use some virtual functions, so I need to execute this BEFORE beginning the destruction process, so the virtual functions calls will not fail.
Is there a way to achieve this?
I attach a basic code snipped showing my problem:
class IBase: public QObject {
public:
template<typename T>
static IBase * create() {
IBase * obj=new T;
obj->afterConstruction();
return obj;
}
void destroy() {
this->beforeDestruction();
delete this;
}
protected:
IBase(): fBeforeDestruction(false){}
virtual ~IBase(){
//Try to perform operations, but it is too late....
if (!fBeforeDestruction)
doBeforeDestruction();
}
virtual void doAfterConstruction(){}
virtual void doBeforeDestruction(){}
private:
bool fBeforeDestruction;
void afterConstruction() {
doAfterConstruction();
}
void beforeDestruction(){
fBeforeDestruction=true;
doBeforeDestruction();
}
};
class TSubclass: public IBase {
protected:
TSubclass(){}
virtual ~TSubclass(){}
virtual void doAfterConstruction(){
qDebug()<<"AfterConstruction";
}
virtual void doBeforeDestruction(){
qDebug()<<"BeforeDestruction";
}
private:
friend class IBase;
};
int main(int argc, char *argv[])
{
//QObject *obj=new TSubclass() //Compile time error! Nice!
QObject *obj=IBase::create<TSubclass>();
delete obj;//Wrong! BeforeDestruction is NEVER shown!!! <---- How to change this behaviour?
IBase * obj2=IBase::create<TSubclass>();
//delete obj2; //Compile time error! Nice!
obj2->destroy(); //Nice!
}
EDIT:
After some comments, I have to add to the question that I want to do several operations before the destructor for two reasons:
Virtual calls: The virtual calls are not allowed inside the destructor, since they will not call the overriden functions, but only the functions in the current destroying class.
Dynamic casts downcasting: Some of the things to do involve donwcasting via dynamic_cast. dynamic_cast downcasting inside the destructors always fails.
EDIT 2:
The answer of Ezee works as I needed. Here is my complete code snippet, showing the code, with also a dynamic_cast:
template <typename T>
class TAfterConstructionBeforeDestruction: public T {
public:
~TAfterConstructionBeforeDestruction() {
this->beforeDestruction();
}
protected:
using T::T;
};
class IBase: public QObject {
public:
//Now it can be public, just as the one in QObject!
virtual ~IBase(){}
template<typename T>
static IBase * create() {
//Create a
IBase * obj=new TAfterConstructionBeforeDestruction<T>;
obj->afterConstruction();
return obj;
}
protected:
IBase(){}
virtual void afterConstruction(){}
virtual void beforeDestruction(){}
};
class TSubclass: public IBase {
public:
virtual ~TSubclass(){}
protected:
TSubclass(){}
virtual void afterConstruction(){
qDebug()<<"AfterConstruction";
}
virtual void beforeDestruction();
private:
friend class IBase;
};
class TSubclass2: public TSubclass {
public:
virtual ~TSubclass2(){}
protected:
TSubclass2(){}
virtual void beforeDestruction(){
qDebug()<<"BeforeDestruction from Subclass2";
TSubclass::beforeDestruction();
}
};
void TSubclass::beforeDestruction() {
qDebug()<<"BeforeDestruction";
TSubclass2 * sub=dynamic_cast<TSubclass2*>(this);
if (sub) {
qDebug()<<"We are actually a TSubclass2!";
}
}
int main(int argc, char *argv[])
{
//QObject *obj=new TSubclass() //Compile time error! Nice!
QObject *obj=IBase::create<TSubclass>();
delete obj;//Now it works fine!
IBase * obj2=IBase::create<TSubclass2>();
delete obj2; //It is still succeeding to dynamic_cast to TSubclass2 without any problem!
}
First of all, I must say that calling virtual methods from a constructor or a destructor is a very bad practice.
Call doAfterConstruction() from the constructor of the mose derived descendant of IBase.
Call doBeforeDestruction() from the destructor of the mose derived descendant of IBase.
You can do the same using signals/slots:
Declare a signal beforeDestroyed() in IBase (add Q_OBJECT macro also).
In the constructor of IBase connect this signal to a slot doBeforeDestruction (make it a slot).
In the destructor of the mose derived descendant of IBase emit the signal: emit beforeDestroyed().
If you have a lot of descendants you may want to avoid doing the same thing in every constructor/destructor. In this case you can use a template also:
template <class T>
class FirstAndLastCall : public T
{
public:
FirstAndLastCall ()
{
doAfterConstruction();
}
~FirstAndLastCall
{
doBeforeDestruction();
}
}
Usage:
IBase* obj2 = new FirstAndLastCall<TSubclass>();
Related
How to avoid The private function calling indirectly using base class virtual function.
class baseclass{
public:
virtual void printmynumber() = 0;
};
class derivedclass : public baseclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
baseclass *bObj = new derivedclass(10);
bObj->printmynumber();
delete bObj;
}
How to avoid the calling of private function?
You cannot.
void printmynumber() is part of the public API of baseclass, hence of derivedclass. If you wished derivedclass::printmynumber() not to be public, maybe derivedclass shouldn't inherit from baseclass.
As suggested in the comments, this is a violation of the Liskov substitution principle: the L in SOLID.
You can't do that with inheritance. Given a pointer to baseclass, the compiler only knows it has a public virtual function, so allows calling the function accordingly.
The derived class has elected to inherit from the base class, and has implemented a function with different access. But none of that is visible, given only a pointer to the base.
There is nothing preventing derivedclass::printmynumber() from being implemented to do nothing - which means if code calls it, there will be no observable effect (assuming absence of an expected effect is tolerable).
The real solution is to fix your design, not to try to work around deficiencies in it. Don't inherit derivedclass from baseclass. That way, no member function of derivedclass can be called at all, given only a pointer to baseclass, since the types are not related (passing a derivedclass * to a function expecting a baseclass * will normally be diagnosed as an error).
BTW: main() returns int, not void. Some compilers support void main() as a non-standard extension (and the documentation for some of those compilers falsely describes such a thing as standard) but it is better avoided.
The only way I can see to prevent it without modifying the base class, is to add another inheritance-layer between between the original base-class and the final derived class. In that middle class you make the function private or deleted. And then you use a pointer to that middle class as the base pointer.
Something like
class baseclass
{
public:
virtual void printmynumber() = 0;
};
struct middleclass : public baseclass
{
void printmynumber() = delete;
};
class derivedclass : public middleclass
{
private:
int m_mynumber;
void printmynumber()
{
cout << m_mynumber << endl;
}
public:
derivedclass(int n)
{
m_mynumber = n;
}
};
void main()
{
// Here use the middleclass instead of the baseclass
middleclass *bObj = new derivedclass(10);
// printmynumber is deleted in the middleclass and can't be called
// This will result in a build error
bObj->printmynumber();
delete bObj;
}
This of course requires modifications of all places where the original base class is used, but it won't need modifications to the base class itself. So it's a trade-off.
Let's say I have the following code:
class BaseMember
{
};
class DerivedMember : public BaseMember
{
};
class Base
{
private:
BaseMember* mpMember;
protected:
virtual BaseMember* initializeMember(void)
{
return new BaseMember[1];
}
virtual void cleanupMember(BaseMember* pMember)
{
delete[] pMember;
}
public:
Base(void)
: mpMember(NULL)
{
}
virtual ~Base(void)
{
cleanupMember(mpMember);
}
BaseMember* getMember(void)
{
if(!mpMember)
mpMember = initializeMember();
return mpMember;
}
};
class Derived : public Base
{
protected:
virtual BaseMember* initializeMember(void)
{
return new DerivedMember;
}
virtual void cleanupMember(BaseMember* pMember)
{
delete pMember;
}
};
Base and BaseMember are parts of an API and may be subclassed by the user of that API, like it is done via Derived and DerivedMember in the example code.
Base initializes mpBaseMember by a call to it's virtual factory function initializeMember(), so that the derived class can override the factory function to return a DerivedMember instance instead of a BaseMember instance.
However, when calling a virtual function from within a base class constructor, the base implementation and not the derived class override gets called.
Therefor I am waiting with the initialization of mpMember until it gets accessed for the first time (which of course implies, that the base class and any derived class, that may could get derived further itself, are not allowed to access that member from inside the constructor).
Now the problem is: Calling a virtual member function from within the base base destructor will result in a call of the base class implementation of that function, not of the derived class override.
That means that I can't simply call cleanupMember() from within the base class destructor, as that would call it's base class implementation, which may not be able to correctly cleanup the stuff, that the derived implementation of initializeMember() has initialized.
For example the base class and the derived class could use incompatible allocators that may result in undefined behavior when getting mixed (like in the example code - the derived class allocates the member via new, but the base class uses delete[] to deallocate it).
So my question is, how can I solve this problem?
What I came up with is:
a) the user of the API has to explicitly call some cleanup function before the Derived instance gets destructed. That can likely be forgotten.
b) the destructor of the (most) derived class has to call a cleanup function to cleanup stuff which initialization has been triggered by the base class. That feels ugly and not well designed as ownership responsibilities are mixed up: base class triggers allocation, but derived class has to trigger deallocation, which is very counter-intuitive and can't be known by the author of the derived class unless he reads the API documentation thoroughly enough to find that information.
I would really like to do this in a more fail-proof way than relying on the users memory or his reliability to thoroughly read the docs.
Are there any alternative approaches?
Note: As the derived classes may not exist at compile time of the base classes, static polymorphism isn't an option here.
What about a modification of the factory pattern that would include the cleanup method? Meaning, add a attribute like memberFactory, an instance of a class providing creation, cleanup, as well as access to the members. The virtual initialization method would provide and initialize the right factory, the destructor ~Base would call the cleanup method of the factory and destruct it.
(Well, this is quite far from the factory pattern... Perhaps it is known under another name?)
If you really want to do this sort of thing you can do it like this:
class Base {
BaseMember* mpMember;
protected:
Base(BaseMember *m) : mpMember(m) {}
virtual void doCleanupMember(BaseMember *m) { delete [] m; }
void cleanupMember() {
// This gets called by every destructor and we only want
// the first call to do anything. Hopefully this all gets inlined.
if (mpMember) {
doCleanupMember(pmMember);
mpMember = nullptr;
}
}
public:
Base() : mpMember(new BaseMember[1]) { }
virtual ~Base(void) { cleanupMember(); }
};
class Derived : public Base {
virtual void doCleanupMember(BaseMember *m) override { delete m; }
public:
Derived() : Base(new DerivedMember) {}
~Derived() { cleanupMember(); }
};
However there are reasons this is a bad idea.
First is that the member should be owned an exclusively managed by Base. Trying to divide up responsibility for Base's member into the derived classes is complicated and just asking for trouble.
Secondly the ways you're initializing mpMember mean that the member has a different interface depending on who initialized it. Part of the problem you've already run into is that the information on who initialized the member has been destroyed by the type you get to ~Base(). Again, trying to have different interfaces for the same variable is just asking for trouble.
We can at least fix the first problem by using something like shared_ptr which lets up specify a deleter:
class Base {
std::shared_ptr<BaseMember> mpMember;
public:
Base(std::shared_ptr<BaseMember> m) : mpMember(m) { }
Base() : mpMember(std::make_shared<BaseMember>()) { }
virtual ~Base() {}
};
class Derived : virtual public Base {
public:
Derived()
: Base(std::shared_ptr<BaseMember>(new DerivedMember[1],
[](BaseMember *m){delete [] m;} ) {}
};
This only hides the difference in the destruction part of the member's interface. If you had an array of more elements the different users of the member would still have to be able to figure out if mpMember[2] is legal or not.
First of all, you must use RAII idiom when developing in C++. You must free all your resources in destructor, of course if you don't wish to fight with memory leaks.
You can create some cleanupMember() function, but then you should check your resources in destructor and free them if they are not deleted (as cleanupMember can be never called, for example because of an exception). So add destructor to your derived class:
virtual ~Derived()
{
Derived::cleanupMember(mpMember);
}
and manage the member pointer in the class itself.
I also recommend you to use smart pointers here.
Never never never call virtual methods in constructor/destructor because it makes strange results (compiler makes dark and weird things you can't see).
Destructor calling order is child and then parent
You can do like this (but there is probalby a better way) :
private:
// private destructor for prevent of manual "delete"
~Base() {}
public:
// call this instead use a manual "delete"
virtual void deleteMe()
{
cleanupMember(mpMember);
delete this; // commit suicide
}
More infos about suicide :
https://stackoverflow.com/a/3150965/1529139 and http://www.parashift.com/c++-faq-lite/delete-this.html
PS : Why destructor is virtual ?
Let mpMember be protected and let it be initialized in derived class constructor and deallocated in derived destructor.
Inspired by the ideas from https://stackoverflow.com/a/19033431/404734 I have come up with a working solution :-)
class BaseMember
{
};
class DerivedMember : public BaseMember
{
};
class BaseMemberFactory
{
public:
virtual ~BaseMemberFactory(void);
virtual BaseMember* createMember(void)
{
return new BaseMember[1];
}
virtual void destroyMember(BaseMember* pMember)
{
delete[] pMember;
}
};
class DerivedMemberFactory : public BaseMemberFactory
{
virtual BaseMember* createMember(void)
{
return new DerivedMember;
}
virtual void destroyMember(BaseMember* pMember)
{
delete pMember;
}
};
class Base
{
private:
BaseMemberFactory* mpMemberFactory;
BaseMember* mpMember;
protected:
virtual BaseMemberFactory* getMemberFactory(void)
{
static BaseMemberFactory fac;
return &fac;
}
public:
Base(void)
: mpMember(NULL)
{
}
virtual ~Base(void)
{
mpMemberFactory->destroyMember(mpMember);
}
BaseMember* getMember(void)
{
if(!mpMember)
{
mpMemberFactory = getMemberFactory();
mpMember = mpMemberFactory->createMember();
}
return mpMember;
}
};
class Derived : public Base
{
protected:
virtual BaseMemberFactory* getMemberFactory(void)
{
static DerivedMemberFactory fac;
return &fac;
}
};
I have a weird C++ problem where I'm not sure if it works correctly this way or If I missed something.
There is a class A which inherits from ABase. ABase and A both have a method Generate() while A::Generate() should overwrite ABase::Generate().
Generate() is called out of the constructor of ABase.
Now my problem:
I do a new A() which first jumps into constructor of A and from there into constructor of ABase. ABase::ABase() now calls Generate(). What I want to do: A::Generate() should be executed (since this overwrites ABase::Generate()).
Unfortunately it seems out of the constructor of ABase only ABase::Generate() is called and never A::Generate().
I gues that happens because A is not fully constructed at this stage? Or is there a way to let ABase::ABase() make use of A::Generate()?
You do not want A::Generate() to be executed, since this
would involve executing a function on a class which has not been
constructed. C++ has been designed intentionally so that during
construction, the dynamic type of the object is the type being
constructed, precisely to avoid this sort of problem.
It's not easy to work around, and definitely not pretty, but you may be able to do something like this:
class ABase
{
public:
ABase()
{
// Normal constructor, calls `Generate`
}
virtual void Generate() { ... }
// ...
protected:
struct do_not_call_generate_tag {};
const static do_not_call_generate_tag do_not_call_generate;
ABase(const do_not_call_generate_tag)
{
// Same as the normal `ABase` constructor, but does _not_ call `Generate`
}
};
class A : public ABase
{
public:
A()
: ABase(ABase::do_not_call_generate)
{
// Other initialization
PrivateGenerate();
}
void Generate()
{
PrivateGenerate();
}
private:
void PrivateGenerate()
{
// Do what your old `Generate` does
}
};
In order to have nicely constructed and initialized objects, I would separate these two tasks from each other:
class ABase
{
public:
virtual void Generate()
{
//...
}
};
class A: public ABase
{
public:
virtual void Generate()
{
//...
}
};
Now you have to perform both tasks explicitly
A *someA = new A();
someA->Generate();
...but you can group this inside e.g. a Create() method or redefine the new operator or the like.
In Java it's possible to write an abstract, super class with unimplemented, abstract methods and non-abstract methods which invoke the abstract methods. Then in the subclass are the abstract methods implemented. When you then make an instance of the subclass, the super class uses the implementations in the subclass. How do I accomplish this in C++?
Here is what I mean, but in Java:
SuperClass.java
public abstract class SuperClass {
public SuperClass() {
method();
}
private void method() {
unimplementedMethod();
}
protected abstract void unimplementedMethod();
}
SubClass.java
public class SubClass extends SuperClass {
public SubClass() {
super();
}
#Override
protected void unimplementedMethod() {
System.out.println("print");
}
public static void main(String[] args) {
new SubClass();
}
}
Would be awesome if you showed me how this is accomplished in C++. :)
In general, what you are looking for, is the virtual keyword. In a nutshell virtual declares the intent that this method can be overriden. Note that such a method can still have an implementation- virtual just makes it overrideable. To declare an "abstract method", you can say declare intent of please provide an implementation in the derived class with = 0, as shown below. Such methods are called pure virtual in C++.
However, there are some caveats that you should watch out for. As pointed out in a comment below, you were calling method() from within the SuperClass constructor. Unfortunately this is not possible in C++, due to the order in which objects are constructed.
In C++ a derived class constructor immediately calls it's superclass constructor before allocating its members or executing the body of the constructor. As such, the members of the base class are constructed first, and the derived class' members are constructed last. Calling a virtual method from a base class will not work as you expect in Java, since the derived class has not been constructed yet, and thus the virtual methods have not been redirected to the derived implementations yet. Hope that makes sense.
However, calling method() on a SuperClass object after creation will work as you expect: it would call the virtual function which would output "print".
class SuperClass {
public:
SuperClass() {
// cannot call virtual functions from base constructor.
}
virtual ~SuperClass() { } // destructor. as Kerrek mentions,
// classes that will be inherited from,
// should always have virtual destructors.
// This allows the destructors of derived classes
// to be called when the base is destroyed.
private:
void method() {
unimplementedMethod();
}
protected:
virtual void unimplementedMethod() = 0; // makes method pure virtual,
// to be implemented in subclass
}
SubClass.h
class SubClass : public SuperClass {
public:
SubClass() : SuperClass() { // how the superclass constructor is called.
}
// no need for "override" keyword, if the methd has the same name, it will
// automatically override that method from the superclass
protected:
void unimplementedMethod() {
std::cout << "print" << std::endl;
}
}
In C++, you should never call virtual functions in the constructor, so it doesn't work quite as literally. Best to use a separate member function
class SuperClass
{
public:
void action() { method(); } // not in the constructor, please
virtual ~SuperClass() { } // always a virtual destructor when polymorphic
protected:
void method() { unimplementedMethod(); }
private:
virtual void unimplementedMethod() = 0;
};
class SubClass : public SuperClass
{
private:
virtual void unimplementedMethod() { std::cout << "print" << std::endl; }
// no need to spell out the next couple of functions, but for your entertainment only
public:
SubClass() : SuperClass() { }
virtual ~SubClass() { }
};
Now to invoke:
int main()
{
SuperClass * p = new SubClass; // construct first...
p->action(); // ... then invoke, after construction is complete
delete p; // thank god for that virtual destructor!
}
The base constructor runs before the derived class is constructed, so you cannot call any derived functions in the base constructor, and in particular you cannot call any pure-virtual functions.
Note that you have the private and protected the wrong way round: The non-virtual accessor function should be protected so it can be used in the entire class hierarchy, but the virtual implementation function should be private, since it only needs to be seen by the accessor function in the same class. In a nutshell: protected-nonvirtual and private-virtuals.
(The usage example is a bit contrived, since you wouldn't normally use new or raw pointers in C++.)
In C++ these are called pure virtual functions/methods.
Basically you tack a "=0" at the end of a method:
virtual doSomething() = 0; // pure virtual
Search around SO for "c++ pure virtual" and you'll find tons of answers.
You need to use virtual methods. The implementation works like this:
/* here's MyBaseClass.h */
class MyBaseClass
{
public:
MyBaseClass(void);
~MyBaseClass(void);
void MyMethod();
protected:
virtual void MyUnimplementedMethod() = 0;
};
/* here's MyIneritedClass.h */
class MyInheritedClass :
public MyBaseClass
{
public:
MyInheritedClass(void);
~MyInheritedClass(void);
protected:
virtual void MyUnimplementedMethod();
};
/* here's the implementation of the method in the base class */
void MyBaseClass::MyMethod()
{
MyUnimplementedMethod();
}
/* and here's the implementation of the abstract method in the derived */
void MyInheritedClass::MyUnimplementedMethod()
{
_tprintf(L"Hello, world");
}
You declare the method as virtual:
snippet:
class Parent{
public:
virtual int methodA() {return methodB();}; // calls the abstract method
virtual int methodB() = 0; // "=0" means pure virtual, not implemented in the base
}
class Child : public Parent{
public:
virtual int methodB() { /* implementation */}
}
virtual means the child may override the implementation and the parent should be then calling the overriden implementation. Adding "=0" to the declaration of the virtual method makes it pure virtual, i.e.: the base doesn't have an implementation of its own, and relies on the implementation by the child. Such class cannot be instantiated (i.e.: abstract class).
class base
{
public:
virtual void start();
virtual void stop();
void doSomething() { start(); .... stop(); }
}
class derived : public base
{
public:
void start();
void stop();
}
But when I call doSomething() in the derived class it is using it's own definition of Start() and Stop() - not the derived ones.
I don't want to rewrite doSomething() in the derived class because it would be identical to the base one. What am I doing wrong?
Sorry if that wasn't clear.
The behaviour of Start() and Stop() in the derived class is different (it's a different machine) - but I want to use the original base class doSomething() because that hasn't changed. It just has to start() and stop() using the new derived class code.
The code you've posted should work the way you want. Calling doSomething on an instance of derived will call the overridden start and stop functions defined in derived.
There's an exception to that, though. If you call doSomething in the constructor or destructor of base (whether directly or indirectly), then the versions of start and stop that get called will be the ones defined in base. That's because in those circumstances, you don't actually have a valid derived instance yet. It's either not fully constructed or partially destructed, so the language prevents you from calling methods that would use the partial object.
If you're not calling it from a base constructor or destructor, then there is more to the problem than what's shown here.
Update
Based on your comment below that you are trying to make doSomething() call the Derived class's version of start() and stop(), my updated answer to your question is as follows:
There is nothing wrong with the way that you defined Base and Derived. You are probably experiencing what is called "code slicing", where you are calling "doSomething()" on an object whose declared type is "Base", instead of "Base*" or "Base&", which will result in the object being converted to type Base.
Bad example:
Derived derived;
Base base = derived;
base.doSomething(); // This is Base's version of doSomething()
Good example:
Base* base = new Derived; // NOTE: declared type is "Base*"
base->doSomething(); // This will call Derived version
delete base;
Side-note: you should use a scoped_ptr, shared_ptr, unique_ptr, or some other smart pointer class instead of using a pointer directly as in my example; however, to not obscure the issue, I have opted to use a raw pointer in this example. For more information about "slicing", see:
What is the slicing problem in C++? - StackOverflow
Slicing in C++
Original solution
You could do something like this:
class Base {
public:
Base() {}
virtual ~Base() {}
virtual void start() {
startInternal();
}
virtual void stop() {
stopInternal();
}
void doSomething() {
startInternal();
// ...
stopInternal();
}
private:
void startInternal() {
// ...
}
void stopInternal() {
// ...
}
};
class Derived : public Base {
public:
Derived() {}
virtual ~Derived() {}
virtual void start() {
// ...
}
virtual void stop() {
// ...
}
};
If you do this, then doSomething() will use the internal version of start/stop which isn't overridden. You will find this pattern a lot, when a constructor/destructor needs to share logic with a virtual method.
Also, not related to the issue at hand, don't forget that you should always create a virtual destructor whenever you create a class that has virtual methods.