tags:

views:

71

answers:

1

Hi. C++ beginner here.

If I have a class called "Animal", and a derived class "Bird : public Animal", I can create a Bird these two ways:

Animal *sparrow = new Bird;
Bird *sparrow = new Bird;

Both compile fine and work as expected. Are they equivalent? Should I prefer one over the other?

+5  A: 

The line, in itself, doesn't demonstrate the difference. However, assume Bird declares a method Fly that doesn't exist on Animal. You wouldn't be able to do:

Animal* a = new Bird;
a->Fly();

on the other hand, this is legal:

Bird* b = new Bird;
b->Fly();

The distinction here is a result of the fact that C++ is a statically typed language. The static type of the variable is what the compiler cares about when it's verifying things like method calls. Since the static type of the variable a is Animal which doesn't have a Fly method, the compiler will not allow you to call Fly on it (not all animals are able to fly, so you'll have to explicitly cast to Bird: dynamic_cast<Bird*>(a)->Fly() is legal).

The expression new Bird will have the type Bird*. If you assign a value of a derived type to a variable of a based type, the compiler will not complain (all Birds are Animals, so it should always work). Basically, the compiler upcasts Bird* to Animal*. The reverse is not true. Not all Animals are Birds, so you'll have to take the responsibility and do the cast explicitly and tell the compiler that I know that object is really a Bird*. Only in that case the compiler will let you to use Bird-specific features. So, in general, if you need to use a Bird-specific member, you'd better use Bird* b = new Bird;.

Mehrdad Afshari
I think I understand. A follow up to clear it in my mind:Animal *A = new Animal;Animal *B = new Bird;With these declarations, is there any difference between A and B? (question asked before some edits above)
Jarred
@Jarred: Yes, the object pointed by `A` is not really a `Bird` whereas the object pointed by `B` is still really a `Bird` and you simply decided not to care at the moment that it is (since your function applies to all animals equally and doesn't rely on anything specific to birds). Since `B` is a `Bird`, you can successfully downcast it to `Bird*` again and use `Bird` specific members. Casting `A` to `Bird*` won't succeed.
Mehrdad Afshari
Thank you very much for your helpful answers.
Jarred