parent points to a Parent object, which is NOT a Child object: there is NO CHILD COMPONENT of the
object is your code. The dynamic_cast<Child*> is attempting to obtain the corresponding Child*
pointer for the object, but as the object is NOT a Child, the cast returns null. You should check
the value after the dynamic_cast before using it!
The NULL value is returned in both scenarios, i.e. regardless of whether print() is virtual.
In the scenario where print has been declared virtual, child->print() will call the /virtual/
function print() for the object, which is accessed through the virtual function table at the
beginning of the object. Since child is null, this will result in an access violation.
If print is not virtual, then child->print() will call the print() function appropriate for a Child
object, which is the Parent::print() method it inherits from the Parent base class. The compiler
knows where that is in memory, so it just calls that method. In your example when that method gets
called, its 'this' pointer will be null, WHICH IS INVALID!! However, it 'works' because nothing in
the method uses the 'this' pointer , i.e. nothing accesses any Parent member variables. If you
changed Parent::print() to access some member variable then we would get some kind of access
violation again.
So the problem is you're trying to access Child objects, but nowhere have you actually created any
Child object in your program! And you're ignoring the dynamic_cast return value which obscures the
problem.
Possibly what you wanted to do was create a Parent* pointer to a Child object, then cast that to get
a Child* pointer:
Parent* parent = new Child(); // note, we create a Child, not a Parent
Child * child = dynamic_cast<Child*>(parent); // ..so now this cast works regardless of whether
child->print(); // print() is virtual
If print() is declared virtual, child->print() will call the print method appropriate for the Child
class - but that is the inherited Parent::print() method! So perhaps Emo does not understand the
purpose of the virtual keyword... To reveal the difference, we need to make an example where both
the Parent and Child classes have their own version of the print() method, and look at how
parent->print() and child->print() behave:
class Parent
{
public:
Parent(){}
virtual void print(){ std::cout << "parent " << "\n"; }
virtual void pt(){ }
};
class Child : public Parent
{
public:
Child(){}
virtual void print(){ std::cout << "child " << "\n"; }
};
int main(int argc, char const *argv[])
{
// Child* old_child = parent; // how to do this??
Parent* parent = new Child();
Child * child = dynamic_cast<Child*>(parent);
parent->print();
child->print();
return 0;
}
Since the methods above are virtual, the parent->print() and child->parent() calls both call the
Child::print() method, because the object involved is created as a Child object.
If we removed the virtual keywords, the parent->print() would call the Parent::print() method, and
child->parent() method would call the Child::print() method. (i.e. based on the types of *parent
and *child.)
Regards,
Mike.