Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

null on dynamic cast of derived class

44 views
Skip to first unread message

fir

unread,
Jan 19, 2023, 4:33:49 PM1/19/23
to
i do not touch c++ (which i name kuc++) so i dont know the answer

my colegue emo want to ask why is that that is she pits a word
virtual before print methid the dynamic cast gives null but
when removes it the print is excecuted

tnx for answer


#include <QCoreApplication>
#include <iostream>

class Parent
{
public:
Parent(){}
virtual void print(){ std::cout << "parent" << "\n"; }
virtual void pt(){ }
};

class Child : public Parent
{
public:
Child(){}
};

int main(int argc, char const *argv[])
{
// Child* old_child = parent; // how to do this??

Parent* parent = new Parent();
Child * child = dynamic_cast<Child*>(parent);
child->print();
return 0;
}

Bo Persson

unread,
Jan 19, 2023, 5:06:02 PM1/19/23
to
No reason. Invalid code can do just about anything.

When you cross the street aginst a red light, sometimes you are run over
by a bus, sometimes not. What are the rules?

fir

unread,
Jan 19, 2023, 5:10:05 PM1/19/23
to
and which one here is invalid?

fir

unread,
Jan 19, 2023, 5:53:10 PM1/19/23
to
overally imo whole kuc++ is incalid

specifically all the so called inheritance is invalid

imo probably better way to do it would be like that
say you got a lot of various different objects/entities
and if some has a set of some methids like .jump()
.walk*( .sleep() rgere shoulkd be no pgtsical constraint
on how it is placed etc
possibly it only should inform that it conforms to some abstract
interfaces

red floyd

unread,
Jan 19, 2023, 6:25:51 PM1/19/23
to
The nullptr response from dynamic cast is correct, because child doesn't
point to a Child, it points to a Parent. dynamic cast realizes this
and returns nullptr.

fir

unread,
Jan 19, 2023, 6:35:20 PM1/19/23
to
okay, tnx for answers... overally its emo problem not mine

Mike Terry

unread,
Jan 19, 2023, 6:38:25 PM1/19/23
to
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.

fir

unread,
Jan 19, 2023, 6:39:44 PM1/19/23
to
piątek, 20 stycznia 2023 o 00:25:51 UTC+1 red floyd napisał(a):
> The nullptr response from dynamic cast is correct, because child doesn't
> point to a Child, it points to a Parent. dynamic cast realizes this
> and returns nullptr.

emo answered:

<Emo>
00:34 ale to sie nie odnosi dlaczego ten keyword virtual powoduje crash

but it doesn't address why this keyword virtual is cousing crash

(without virtual the cast is also logically invalid but there is no crash)

fir

unread,
Jan 19, 2023, 7:01:02 PM1/19/23
to
piątek, 20 stycznia 2023 o 00:38:25 UTC+1 Mike Terry napisał(a):
> On 19/01/2023 21:33, fir wrote:
> > i do not touch c++ (which i name kuc++) so i dont know the answer

> knows where that is in memory, so it just calls that method. In your example when that method gets


does nor ut yeild to conclusion that dynamic cast where virtuial is used return null but when is not used dont return null but passes the pointer? if so why is that?

fir

unread,
Jan 19, 2023, 7:10:13 PM1/19/23
to
piątek, 20 stycznia 2023 o 00:38:25 UTC+1 Mike Terry napisał(a):
> 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

overally i think emo overlooked that you cant cast base to derived.. i also ovverlooked this as im tired and this is not my problem.. this explaind why its
bad, though she also would like to understand the details

(for me personally its not much importand as i find all thet inheritance bad.. i use c normally and c is 'physical' language..if i want to do such things i use
separate arrays for each typenot put things in one bag... in turn when someone would do that abstract way they should do it fully abstract. like say int and float has some common anstract denominator but iut cant be expressed in a form of c++ ingeritance.. c++ uses a bit of physical attempt mixed with a bit of abstract and it is not good solution imo - but it is side topic here)

Mike Terry

unread,
Jan 19, 2023, 7:19:40 PM1/19/23
to
No - in both cases dynamic_cast returns null, because its argument (parent) does not point to a
Child object. The different behaviour between virtual/not virtual keyword is because virtual causes
the null value to be dereferenced, in order to look up the objects virtual function table to find
the right print() function to call. Dereferencing null gives the access violation. If virtual is
not specified, the compiler does not use the object's virtual function table, because it already
knows which print() function to call and the address of that print function. So the null value is
never dereferenced in this case and there is no access violation, although the code is still incorrect.

To see this you could just step through the code in a debugger and verify that child is null in both
scenarios. Or add something to print the value of child after the cast...

Mike.

Mike Terry

unread,
Jan 19, 2023, 7:24:51 PM1/19/23
to
On 20/01/2023 00:10, fir wrote:
> piątek, 20 stycznia 2023 o 00:38:25 UTC+1 Mike Terry napisał(a):
>> 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
>
> overally i think emo overlooked that you cant cast base to derived.. i also ovverlooked this as im tired and this is not my problem.. this explaind why its
> bad, though she also would like to understand the details

It is ok to cast from the base class to a derived class - BUT IT ONLY WORKS IF THE BASE CLASS
POINTER ACTUALLY POINTS TO AN INSTANCE OF THE DERIVED CLASS. In your code, parent does not point to
an instance of Child, so null is returned.

I hope she would be able to follow the explanation I originally gave. If not she could ask more
questions here. :)


Mike.

fir

unread,
Jan 19, 2023, 7:35:07 PM1/19/23
to
buy yjere is such line in this code

child->print();

toy say it call print methid even if child is NULL ? if so its quite new to me

Mike Terry

unread,
Jan 19, 2023, 8:37:09 PM1/19/23
to
Yes, when the print() method is not virtual, the compiler knows which method to call just based on
the types used in the expression. In this case child is declared as type Child*, so 'child->' tells
the compiler that the print method is for the Child class - or its base class if Child does not have
its own print method. So here it will generate code to call Parent::print. The child-> term also
tells the compiler to set the 'this' pointer within the method to the value of child, which is null,
but if the 'this' pointer is not used (i.e. no object members accessed) you might get away with it.
Or you might not, it depends on the compiler generated code.

If Parent were like this:

class Parent
{
public:
Parent(){}
virtual void print(){ std::cout << "parent" << num << "\n"; }
virtual void pt(){ }

int num = 7;
};

then the printing of member variable 'num' would try to dereference the null 'this' pointer and
generate an access violation of some kind.

Anyway, it's Wrong to call child->print(); if child is null. Even if it apparently works correctly
with a given compiler...

Mike.






fir

unread,
Jan 20, 2023, 3:53:21 AM1/20/23
to
shocking...ok emo praised this group, .. maybe we will get back in some future..tnx (i stick to c but emo uses qt and unreal engine)

Paavo Helde

unread,
Jan 20, 2023, 6:25:07 AM1/20/23
to
Undefined behavior is undefined and can do anything. If it was
guaranteed crash, it would be a defined behavior.

0 new messages