Polymorpishm in C++ - c++

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.

Related

How to construct a class with an existing base class pointer?

I have one base class and two derived child's (different classes).
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
In pseudo code this would look like this:
class Parent
{
public:
int x;
};
class ChildA : public Parent
{
void setX() {x=5;}
};
class ChildB : public Parent
{
int getX() {return x;} //Shall return 5 after calling the set method of ChildA first
};
//Creating instances
ChildA* a;
a = new ChildA();
Parent* ptrToBaseClass = a;
ChildB* b;
b = new ChildB(); //How can I set this to the same base class ptr (Parent*) which instance “a” has?
How can this be achieved with passing the base class pointer?
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
What you would like is not possible. Each base class sub object is stored within the most derived object.
You can use the existing base to copy initialise the base of another object, but they will be separate.
What you could do to achieve something similar, is to use indirection:
struct Parent
{
std::shared_ptr<int> x = std::make_shared<int>();
};
struct ChildA : Parent
{
void setX() {*x=5;}
};
struct ChildB : Parent
{
int getX() {return *x;} //Shall return 5 after calling the set method of ChildA first
};
int main() {
ChildA a;
Parent& a_base = a;
ChildB b {a_base}; // note that the base is copied here
a.setX();
std::cout << b.getX();
}
This way even though the base objects are separate, they both refer to shared state.
A simpler solution is to store the state in static storage (such as static member, as suggested by Ahmet). But this will make the state shared across all instances while the indirection allows exact control over which objects share which state.
You can make the x in Parent class static. This will allow you to do this - although I have to warn you that this is quite a dodgy code and can bite you in the a**.
Of course, then you have to access it with rather than just x; as Parent::x.
EDIT: I seem to got it wrong. If you want the whole base class as 'shared' rather than just x; you need pointers and custom logic to manage it - there is no direct language construct.

Why does "this" change in parent of class with multiple base classes?

(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

Inheritance: use inherited methods from parent pointer

I'm working with some production code, some of which I cannot safely modify (without breaking things). My issue is that it I would like to use a specific method, one of the parameters of which is a pointer to a class. However the class as the parameter does not do what I want it to.
So I wrote a sub-class of that class and am attempting to call the above function, but it still uses the parent class' methods.
I have a MWE below:
#include <iostream>
class Parent
{
public:
Parent() {};
void method() {std::cout<<"in Parent\n";}
};
class Child : public Parent
{
public:
Child() {};
void method() {std::cout<<"in Child\n";}
};
void secondMethod(Parent* Pptr)
{
Pptr->method();
}
int main()
{
Child c = Child();
Parent* parentPtr = &c;
c.method();
parentPtr->method();
secondMethod(parentPtr);
secondMethod(&c);
return 0;
}
In the above example running this the output is of course:
in Child
in Parent
in Parent
in Parent
I believe the issue is slicing? Basically I'm casting to the pointer of the parent class, so it is considered as a Parent.
I have seen some ways around this by making methods virtual in the parent class but I don't have that option.
Is there some way to make secondMethod actual use the child's method? Specifically without changing the Parent class OR the secondMethod.
No not really if you aren't able to change the parent class or 'secondMethod'. The constructor of 'secondMethod' defines its parameter as Parent*. Passing a Child* to 'secondMethod' will cause the Child* to be upcast to Parent* and in turn will cause Parent's implementation of 'method' to be called.
If you can not change method to virtual function, you may can import template to solve your problem.
template<typename T>
void secondMethod(T* Pptr)
{
Pptr->method();
}
it may can work!!!

how to access child instances

#include<stdio.h>
class parent
{
public:
parent()
{
}
};
class child : public parent
{
public:
child()
{
}
};
class master
{
public:
void view(parent a)
{
printf("view parent instances");
}
void view(child b)
{
printf("view child instances");
}
};
int main()
{
parent *ptr;
master mymaster;
ptr = new child;
mymaster.view(*ptr);
return 0;
}
output : "view parent instances"
I create a pointer from parent class. then I declared that pointer as child type. when i run mymaster.view(*ptr); , this always go to first view function (void view(parent a)), how to make it go to (void view(child b)). thankyou
With a little refactoring and a slightly different approach, you could use virtual functions. This enables the function from derived classes to be used when called using a pointer like below.
#include<stdio.h>
class parent
{
public:
parent()
{
}
virtual void view()
{
printf("View parent");
}
};
class child : public parent
{
public:
child()
{
}
virtual void view()
{
printf("View child");
}
};
class master
{
public:
void view(parent *a)
{
a->view();
}
};
int main()
{
parent *ptr;
master mymaster;
ptr = new child;
mymaster.view(ptr);
return 0;
}
This will output "View child". The same code without the virtual keywords will output "View parent". Note that the keyword only needs to be in the parent class, but is often used in the derived classes too for clarity.
The Wikipedia article on virtual functions explains the situation pretty well:
Virtual functions are resolved 'late'. If the function in question is
'virtual' in the base class, the most-derived class's implementation
of the function is called according to the actual type of the object
referred to, regardless of the declared type of the pointer or
reference. If it is not 'virtual', the method is resolved 'early' and
the function called is selected according to the declared type of the
pointer or reference.
Since the actual type of the object here is a child, the virtual function makes sure that the child's functionality is called even though the pointer is of parent type.
The type of *(parent*) is parent, so the method that gets called is view(parent). If you want to invoke view(child), you need to cast the pointer to a child* before passing it in, however...
You're using OOP backwards. You don't define multiple methods that know how to consume each specific type of sub-class, you define one method that can respect the contract provided by the parent class, and the sub-classes do their own thing internally.
ptr is a pointer to a parent object.
If you want to have the view(child) function called, you need to pass a child object to the function call.
Alternatively, you can cast it to a child pointer
mymaster.view(*(child*)ptr);
but you're likely to end up with all kinds of other problems.
The compiler decides the matching method according to the best choice.
The compiler sees that the variable is of type parent, so it calls the matching method.

In C++, how can I test if an object is an instance of a Child class in the Parent class' constructor?

I'm trying to assert that a pointer passed into a Parent class' constructor is only NULL if the object is of a specific Child class type using dynamic_cast:
#include <iostream>
class Parent {
public:
Parent(void *ptr);
virtual ~Parent(); // to make Parent polymorphic
};
class Child1 : public Parent {
public:
Child1() : Parent(0) { std::cout << "Child1 ctor\n";};
};
class Child2 : public Parent {
public:
Child2() : Parent(0) { std::cout << "Child2 ctor\n";};
};
Parent::Parent(void *ptr) {
if (0 == ptr && 0 == dynamic_cast<Child1*>(this)) {
std::cerr<<"ERROR\n";
}
}
Parent::~Parent() {};
int main(void) {
Child1 *c1 = new Child1();
Child2 *c2 = new Child2();
}
This prints:
ERROR
Child1 ctor
ERROR
Child2 ctor
Whereas, I expect to see ERROR during the Child2 construction only.
Why is dynamic_cast returning non-NULL when I'm in Parent constructor for Child1 called from Child1's constructor initialization list? Also, is there a different way to accomplish this test?
When you are in Parent constructor -which is a base class- the Child has not been constructed yet. As a result, within the constructor of Parent the dynamic type of this will always be Parent.
I'd guess the issue is that dynamic_cast works off the vtable, which isn't set up until after the constructor finishes. Thus, you can't call dynamic_cast in the constructor.
I can't think of any immediate ways to detect this in the constructor without using templates and making everything static. Why do you want this behaviour? It seems quite dubious - Parent really should have no knowledge of the derivatives Child1 and Child2.
If you want to protect against a null pointer in when Child2 calls the parent constructor, why not just protect against it in Child2's constructor and throw an exception if it is null?
One way to do thins like that would be to create proected constructor in base class, and pass parameter indicating how to initalize it - this way child classes would decide how they want it, and base class would just arrange things as requested.