(Initial note: this question is not the same question as whether or not it is safe to delete a void pointer, though that issue has some relation to the problem identified in Update 2. The question here is why a base class obtains a different value from this than is obtained by the derived class for the same object. In cases where the derived object will call a suicide method of the base class, the base class must have a virtual destructor, and the pointer being deleted must be of type pointer-to-base class; storing it in a void* isn't a safe way to delete an object from a base class method.)
I have a diamond-shaped multiple inheritance where my child class has two parents that both inherit from the same grand-parent, thus:
class Grand
class Mom : public virtual Grand
class Dad : public Grand
class Child : Mom, Dad
I wrote Mom and Child, but Grand and Dad are library classes I didn't write (that's why Mom inherits virtually from Grand, but Dad doesn't).
Mom implements a pure virtual method declared in Grand. Dad does not. Therefore, Child also implements that same method (because otherwise the compiler would object that Dad's declaration of that method, inherited by Child, had no implementation). Child's implementation merely calls Mom's implementation. Here's the code (I've included code for Dad and Grand, as this is a SSCCE, not the code I'm stuck using that relies on library classes I didn't write):
class Grand
{
public:
virtual void WhoAmI(void) = 0;
};
class Mom : public virtual Grand
{
public:
virtual void WhoAmI()
{
void* momThis = this;
}
//virtual int getZero() = 0;
};
class Dad : public Grand
{
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
return Mom::WhoAmI();
}
int getZero()
{
return 0;
}
};
int main()
{
Child* c = new Child;
c->WhoAmI();
return 0;
}
Note that the getZero method in Child is never called.
Stepping through execution with the debugger, I see that the address in Child* c is 0x00dcdd08. Stepping into Child::WhoAmI, I see that the address in void* childThis is also 0x00dcdd08, which is what I expect. Stepping further into Mom::WhoAmI, I see that void* momThis is assigned 0x00dcdd0c, which I interpret to be the address of the Mom subobject of my multiply inherited Child object (but I admit I'm a bit out of my depth at this point).
Okay, the fact that Child's this and Mom's this are different doesn't shock me. Here's what does: if I uncomment the declaration of getZero in Mom, and step through all of that again, Mom::this and Child::this are the same!
How can the addition of virtual int getZero() = 0 to the Mom class result in the Mom subobject and the Child object having the same address? I thought maybe the compiler recognized that all of Mom's methods were virtual and its vtable was the same as Child's, so they somehow became the "same" object, but adding more, and different, methods to each class doesn't change this behavior.
Can anyone help me understand what governs when this is the same for the parent and child of a multiply inherited child and when it is different?
Update
I've tried to simplify things to focus as narrowly as I can on the issue of when this has a different value in a parent object than it has in that parent's child object. To do that, I've changed the inheritance to make it a true diamond, with Dad and Mom both inheriting virtually from Grand. I've eliminated all virtual methods and no longer need to specify which parent class's method I am calling. Instead, I have a unique method in each parent class that will let me use the debugger to see what value this has in each parental object. What I see is that this is the same for one parent and the child, but different for the other parent. Moreover, which parent has the different value changes when the order of the parents is changed in the child's class declaration.
This turns out to have catastrophic consequences if either of the parent objects tries to delete itself. Here's code that, on my machine, runs fine:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x0137dd0c
}
};
class Dad : public virtual Grand
{
public:
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x0137dd08
delete dadIam; // this works
}
};
class Child : Dad, Mom
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x0137dd08
c->WhoAmI();
return 0;
}
However, if I change class Child : Dad, Mom to class Child : Mom, Dad, it crashes at run-time:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
This is a problem when you have a class that includes methods that can delete objects of that class (a "suicide method"), and those methods might be called from derived classes.
But, I think I have found the solution: any base class that includes a method that might delete instances of itself and that might have those methods called from instances of classes derived from that class must have a virtual destructor.
Adding one to the code above make the crash go away:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
virtual ~Dad() {};
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
A number of people I've met are aghast at the idea of an object deleting itself, but it is legal and a necessary idiom when implementing COM's IUnknown::Release method. I found good guidelines on how to use delete this safely, and some equally good guidelines on using virtual destructors to solve this problem.
I note, however, that unless the person who coded your parent class coded it with a virtual destructor, calling any suicide method of that parent class from an instance of a class derived from that parent is probably going to crash, and do so unpredictably. Perhaps a reason to include virtual destructors, even when you don't think you need one.
Update 2
Well, the problem comes back if you add a virtual destructor to both Dad and Mom. This code crashes when it attempts to delete Dad's this pointer, which does not match Child's this pointer:
class Grand
{
};
class Mom : public virtual Grand
{
public:
virtual ~Mom() {};
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
virtual ~Dad() {};
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
virtual ~Child() {};
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
Update 3
Thanks to BeyelerStudios for asking the right question: deleting a void* instead of deleting a Dad* prevented C++ from knowing what it was really deleting and, therefore, stopped it from calling the virtual destructors of the base and derived classes. Replacing delete dadIam with delete this solves that problem, and the code runs fine.
Although it would be somewhat ridiculous, replacing delete dadIam with delete (Dad*)dadIam also runs fine, and helps illustrate that the type of the pointer operated on by delete makes a difference to what delete does. (Something I should hardly find surprising in a polymorphic language.)
BeyelerStudios, if you want to post that as an answer, I'll check the box for you.
Thanks!
As mentioned by the standard [intro.object]:
Objects can contain other objects, called subobjects. A subobject can be [...] a base class subobject [...].
Moreover [expr.prim.this]:
The keyword this names a pointer to the object for which a non-static member function is invoked [...].
It goes without saying that two different classes (derived and base) are different objects, thus can have different values for the this pointer.
Can anyone help me understand what governs when this is the same for the parent and child of a multiply inherited child and when it is different?
When and why they differ is not ruled by the standard (of course, it's mainly due to the existence of a vtable associated to the object, but please note that vtables are simply a common, convenient way to deal with polymorphism and the standard never mentions them).
It usually derives from the chosen/implemented ABI (see here for further details about a common one, the Itanium C++ ABI).
It follows a minimal, working example to reproduce the case:
#include<iostream>
struct B {
int i;
void f() { std::cout << this << std::endl; }
};
struct D: B {
void f() { std::cout << this << std::endl; }
virtual void g() {}
};
int main() {
D d;
d.f();
d.B::f();
}
An example output is:
0xbef01ac0
0xbef01ac4
Related
I am from Java and a bit new to C++.
In Java I would have the possibility to do this: link to code
I create an abstract base class Mother, with one pure virtual function used in a public function of that same base class.
I tried this :
class Mother {
private:
virtual void bar() = 0;
public:
void foo();
};
void Mother::foo() {
// ... some code
bar();
}
class Child0: public Mother {
private:
void bar();
};
void Child0::bar() {
std::cout << "Child0" << std::endl;
}
class Child1: public Mother {
private:
void bar();
};
void Child1::bar() {
std::cout << "Child1" << std::endl;
}
// main code
int main() {
Mother mother;
if(condition) {
Child0 child;
mother = child;
} else {
Child1 child;
mother = child;
}
mother.foo();
}
But I get a compiler error:
main.cpp:35:12: fatal error: variable type 'Mother' is an abstract class
Mother mother;
^
main.cpp:5:22: note: unimplemented pure virtual method 'bar' in 'Mother'
virtual void bar() = 0;
^
What am I missing?
C++, unlike Java, has value semantics and no implicit pointers: when you declare Mother mother; you get an actual instance of Mother. No more, no less. Except in your case, where Mother is abstract: you can't have an instance of Mother!
Doing mother = child; later just assigns the Mother part of the child into mother. This is called "object slicing", because the child part you expected to copy as well is sliced off.
To fix this, you need to use either pointers or references, which can both refer to objects whose dynamic type differ from their static type (e.g, a Mother that is actually a Child0). I'll use the simplest owning pointer, std::unique_ptr:
int main() {
std::unique_ptr<Mother> mother;
if(condition) {
mother = std::make_unique<Child0>();
} else {
mother = std::make_unique<Child1>();
}
// At this point, *mother is of static type Mother,
// but of dynamic type Child0 or Child1.
mother->foo();
}
Note that I have also switched to dynamic allocation: Your two children instances were automatic variables, which means that they die at the end of their scope {}. std::make_unique constructs an object with dynamic lifetime: it will only die when the unique_ptr holding it does.
As noted in the other answer, since your child object will be destructed polymorphically, through the type of Mother, Mother's destructor should be virtual to be dispatched correctly.
class Mother {
// ...
public:
virtual ~Mother() = default;
};
You are missing the object slicing trap, and also have undefined behavior: when you assign
mother = child;
child gets "sliced" down to mother, with any polymorphic behavior removed.
If you wish to retain polymorphism, use pointers:
Mother *mother;
if(condition) {
mother = new Child0;
} else {
mother = new Child1;
}
mother->foo();
delete mother;
Make sure Mother has a virtual destructor.
Note that you can no longer use objects from inner scope, because the pointer would become invalid as soon as the scope ends:
// Do not do this!
Mother *mother;
if(condition) {
Child0 child;
mother = &child;
}
mother->foo(); // <<<=== This is undefined behavior
I am studying inheritance and polymorphism in C++ and I came across this example:
class Parent
{
public:
void a()
{
std::cout << "parentA";
}
virtual void b()
{
std::cout<<"parentB";
}
};
class Child : public Parent
{
public:
void b()
{
std::cout<<"childB";
}
};
Then in main:
int main()
{
Parent i= Child();
i.b(); //why doesn't this give parentB?
Parent *j= new Child();
j->b();
}
The outputs are parentA and childB respectively but I can't understand why. (isn't b() overriding?)
The first case should give parentB, since the object i has type Parent, not Child. The Child object is sliced - that is, its Parent subobject is copied to create i of type Parent, then the temporary Child is destroyed. You can often prevent confusing behaviour like this by making base classes abstract (that is, giving them pure virtual functions), so that they can't be instantiated.
The second case should give childB, since the object that j points to has dynamic type Child.
You have "sliced" the Child class into the Parent class. In order to access virtual methods, you need to store the instance polymorphically, like you have with your second example. Polymorphic variables are pointers and references.
class BaseTest {
protected:
virtual void finalizeParts() {
delete m_part;
};
public:
int* m_part;
BaseTest() {
m_part = new int;
}
void finalize() {
finalizeParts();
delete this;
}
};
class SubTest : public BaseTest {
protected:
void finalizeParts() {
BaseTest::finalizeParts();
delete m_anotherPart;
}
public:
int* m_anotherPart;
SubTest() {
m_anotherPart = new int;
}
};
SubTest* test = new SubTest();
test->finalize();
I am having trouble avoiding virtual function calls inside the destructor of my classes (I hate that C++ forces me to do this in the first place). Overriding the destructor in all my subclasses seems terribly inconvenient compared to a common cleanup strategy in a base class using some virtual functions that can be overridden if needed. As a workaround I'm thinking about introducing a 'finalize' function in my base class that performs the cleanup and finally calls 'delete this'. It's probably a very unusual solution, so I was wondering if I'm approaching this the wrong way and if there's a more obvious way to write 'proper' destructors in C++.
If your object aggregates other objects that manage their resources (think of smart pointers, for example. General principle is called RAII), then there is no need in destructor at all.
Of course, you still need desructor for each such "manager" but it should be much easier to implement because of less information and resources to concern about.
self-deleting in your case seems to be bad approach since no one would expect finalize to free object's memory (principle of least astonishment). Though it may be okay with internal implementation (For example, I once did delete this when was implementing shared_ptr's. Namely, I did it when counter of resource manager reaches 0. But that behavior wasn't exposed to end-user anyway)
Your approach is wrong.
With virtual destructors, destructor of base class will be called as well as destructor of derived class - so you should implement destructor for each derived class, that would delete only relevant portion of derived class, and let destructor of base class to clean base class.
If you have a chain of derived classes, destructor for each level of inheritance will be called - in order from most derived class to the base class.
For your example, all that required is:
class BaseTest {
public:
virtual ~BaseTest () {
delete m_part;
};
int* m_part;
BaseTest() {
m_part = new int;
}
};
class SubTest : public BaseTest {
public:
virtual ~SubTest () {
//~BaseTest() will be called automatically
delete m_anotherPart;
}
int* m_anotherPart;
SubTest() {
m_anotherPart = new int;
}
};
SubTest* test = new SubTest();
delete test;
Is this any simpler to you?
class BaseTest {
public:
std::unique_ptr<int> m_part;
BaseTest() : m_part(new int) {}
virtual ~BaseTest() {}
};
class SubTest : public BaseTest {
public:
std::unique_ptr<int> m_anotherPart;
SubTest() : m_anotherPart(new int) {}
};
SubTest test;
or for that matter,
class BaseTest {
public:
int m_part;
};
class SubTest : public BaseTest {
public:
int m_anotherPart;
};
SubTest test;
I think you have an XY problem. Instead of asking us about your weird reimplementation-of-what-destructors-already-do, ask about the problem you are having with calling virtual functions in your destructors.
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;
}
};
Consider the following simple polymorphism ...
class Parent {
public:
someFunc() { /* implementation A */ };
};
class Child : public Parent {
public:
someFunc() { /* implementation B */ };
};
int main ()
{
Parent* ptr;
ptr = new Parent();
ptr->someFunc();
delete ptr;
ptr = new Child();
ptr->someFunc();
delete ptr;
return 0;
}
As far as I can tell, in both cases implementation A will be called.
How can I call the "most derived" implementation of someFunc, depending on the dynamic type of ptr?
In my real code there are many children types, so it wouldn't be practical to use dynamic_cast to check per child class.
Try:
class Parent
{
public:
virtual someFunc() { /* implementation A */ };
//^^^^^^^
};
Though technically not required.
I always find it good style to also declare the derived function virtual:
class Child : public Parent
{
public:
virtual someFunc() { /* implementation B */ };
};
Unlike Java functions are not virtual by default.
Declare someFunc virtual. This will ensure that the implementation of the actual object is called, not the implementation depending on the pointer type.
This will, however, add some overhead connected with the creation of the VTABLE and slower calling of the virtual function, but is essentially what polymorphism is.
There is no polymorphism here! None of your functions are virtual.
If you want polymorphism, do this:
class Parent {
public:
virtual someFunc() { /* implementation A */ };
};