Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Professional C++ [eng].pdf
Скачиваний:
1715
Добавлен:
16.08.2013
Размер:
11.09 Mб
Скачать

Discovering Inheritance Techniques

{

Romance novel; Book book;

cout << novel.getDescription() << endl; // Outputs “Romance Paperback Book” cout << book.getDescription() << endl; // Outputs “Book”

}

Casting Up and Down

As you have already seen, an object can be cast or assigned to its parent class. If the cast or assignment is performed on a plain old object, this results in slicing:

Super mySuper = mySub; // SLICE!

Slicing occurs in situations like this because the end result is a Super object, and Super objects lack the additional functionality defined in the Sub class. However, slicing does not occur if a subclass is assigned to a pointer or reference to its superclass:

Super& mySuper = mySub; // No slice!

This is generally the correct way to refer to a subclass in terms of its superclass, also called upcasting. This is always why it’s a good idea to make your methods and functions take references to classes instead of directly using objects of those classes. By using references, subclasses can be passed in without slicing.

When upcasting, use a pointer or reference to the superclass to avoid slicing.

Casting from a superclass to one of its subclasses, also called downcasting, is often frowned upon by professional C++ programmers. The reason is that there is no guarantee that the object really belongs to that subclass. For example, consider the following code.

void presumptuous(Super* inSuper)

{

Sub* mySub = static_cast<Sub*>(inSuper); // Proceed to access Sub methods on mySub.

}

If the author of presumptuous() also wrote code that called presumptuous(), everything would probably be okay because the author knows that the function expects the argument to be of type Sub*. However, if another programmer were to call presumptuous(), they might pass in a Super*. There are no compile-time checks that can be done to enforce the type of the argument, and the function blindly assumes that inSuper is actually a pointer to a Sub.

Downcasting is sometimes necessary, and you can use it effectively in controlled circumstances. If you’re going to downcast, however, you should use a dynamic_cast, which uses the object’s built-in knowledge of its type to refuse a cast that doesn’t make sense.

The previous example should have been written as follows.

239