Tải bản đầy đủ (.pdf) (10 trang)

A Complete Guide to Programming in C++ part 56 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (222.48 KB, 10 trang )

529
Type Conversion in Class
Hierarchies
This chapter describes implicit type conversion within class hierarchies,
which occurs in the context of assignments and function calls.
In addition, explicit type casting in class hierarchies is discussed, in
particular, upcasting and downcasting.
chapter
24
530

CHAPTER 24 TYPE CONVERSION IN CLASS HIERARCHIES

CONVERTING TO BASE CLASSES
Example for implicit conversion
#include "car.h"
bool compare( Car&, Car&);
int main()
{
PassCar beetle("New Beetle", false, 3421, "VW"),
miata( "Miata", true, 2512, "Mazda");
bool res = compare( beetle, miata);
//
}
// ok!
// Implicit conversion
// to base class.
// Car& a = beetle;
// Car& b = miata;
bool compare( Car& a, Car& b)
{


// Here a is the base part of beetle,
// b is the base part of miata.
// If this is inconvenient, an explicit
// type cast to type PassCar has to be performed.
}
CONVERTING TO BASE CLASSES

531
ᮀ Implicit Conversion
If a class is derived from another class by public inheritance, the derived class assumes
the characteristics and features of the base class. Objects of the derived class type then
become special objects of the base class, just like an automobile is a special type of vehi-
cle.
You can utilize the is relationship when handling objects. It is possible to assign an
object of a derived class to an object of the base class. This causes an implicit type conver-
sion to a base class type.
The base class thus becomes a generic term for multiple special cases. Given that the
classes PassCar and Truck were derived from the Car class, objects of the PassCar
or Truck type can always be managed like objects of Car type.
ᮀ Assignments
Implicit type conversion in class hierarchies occurs in assignments to
■ base class objects
■ pointers or references to the base class.
ᮀ Function Calls
Additionally, a similar kind of implicit type conversion takes place for the arguments of
function calls.
Given the function compare() with the following prototype
Example: bool compare( Car& , Car& );
and two objects of the derived PassCar class type, beetle and miata, the following
statement is valid

Example: compare( beetle, miata);
The compiler performs implicit type conversion for the arguments beetle and miata,
converting them to the parameter type, that is, to a reference to the base class Car.
Type conversion for arguments used in function calls is similar to the type conversion
that occurs in assignments, as shown in the following section.
532

CHAPTER 24 TYPE CONVERSION IN CLASS HIERARCHIES
auto bmw
nr: 4325
producer:
"Bayer "
nr: 4325
sunRoof: true
producer:
"Bayer "
passCarType:
"520i"

TYPE CONVERSIONS IN ASSIGNMENTS
ᮀ Effect of an assignment
Car auto;
PassCar bmw("520i", true, 4325,
"Bayerische Motorenwerke");
auto = bmw;
TYPE CONVERSIONS IN ASSIGNMENTS

533
ᮀ Assignment to a Base Class Object
An object belonging to a derived class type can be assigned to an object of a base class.

Example: Car auto;
PassCar bmw("520i", true, 4325,
"Bayerische Motorenwerke");
auto = bmw;
The object bmw, which belongs to the derived class PassCar, contains all the data
members of the base class, Car, i.e. the vehicle id number and the manufacturer. During
an assignment the object bmw is copied to the data members of the object auto step by
step.
This makes the above statement equivalent to:
auto.nr = bmw.nr;
auto.producer = bmw.producer;
The data members additionally defined in the derived class are not copied!
The following statement outputs the copied data members:
Example: auto.display();
The fact that you can assign an object belonging to a derived class to a base class object
assumes that more will always fill less. The object on the right of the assignment operator
will always contain a member object of the type on the left of the operator.
ᮀ Assignments to Derived Class Objects
This is not the case when you attempt to assign a base class object to an object of a
derived class. The assignment
Example: bmw = auto; // Error!
is therefore invalid, since the values for the additional data members passCarType and
sunRoof are unknown.
An assignment in reverse order is only possible if you have defined an assignment of
this type or a copy constructor with a parameter of the type “reference to base class.”
Both would be able to supply default values for the additional data members of the
derived classes.
534

CHAPTER 24 TYPE CONVERSION IN CLASS HIERARCHIES

carPtr cabrio
nr
producer
1001
"Triumph"
carType "Spitfire"
sunRoof true

CONVERTING REFERENCES AND POINTERS
ᮀ Effect of a pointer assignment
PassCar cabrio("Spitfire", true, 1001, "Triumph");
Car* carPtr = &cabrio;
carPtr = &cabrio;
CONVERTING REFERENCES AND POINTERS

535
ᮀ Converting to Base Class Pointers
The is relationship between a derived class and a base class is also apparent when refer-
ences and pointers are used. A pointer of the type “pointer to base class,” or base class
pointer for short, can reference an object of a derived class type.
Example: Car* carPtr = &cabrio;
In this case cabrio is an object of the class PassCar.
The following rule applies for access to the referenced object:
■ a base class pointer can only access the public interface of the base class.
The additional members defined in the derived class are therefore inaccessible. To make
this more clear:
Example: carPtr -> display();
calls the display() method in the base class Car. Although carPtr points to an
object of the PassCar class in this case, it is impossible to call any methods additionally
defined in the derived class.

Example: carPtr->setSunRoof(false); // Error
The object *carPtr belongs to the Car class and only represents the generic part of
cabrio. Thus, the following assignment is also invalid
Example: PassCar auto;
auto = *carPtr; // Error!
although carPtr is pointing at an object of the PassCar type in this case!
ᮀ Conversions in References to Base Classes
A similar situation arises when you are working with references. A reference of the type
“reference to base class” can point to an object of a derived class. The reference will
address only the generic part of the object in this case.
Example: Car& carRef = cabrio; // ok
carRef.display(); // Output base members
carRef.setSunRoof(true); // Error
PassCar auto;
auto = carRef; // Error
Although the reference carRef points to an object of the PassCar type, it is impossi-
ble to assign the PassCar type object auto to this object.
536

CHAPTER 24 TYPE CONVERSION IN CLASS HIERARCHIES
Car
PassCar
carPtr
static_cast<PassCar*>(carPtr)
Pointer to
Base class
Derived
class
Downcast
Car

PassCar
static_cast<Car*>(PassCarPtr)
PassCarPtr
Pointer to
Base class
Derived
class
Upcast

EXPLICIT TYPE CONVERSIONS
Downcast
Upcast
EXPLICIT TYPE CONVERSIONS

537
ᮀ Upcasts and Downcasts
Type conversions that walk up a class hierarchy, or upcasts, are always possible and safe.
Upcasting is performed implicitly for this reason.
Type conversions that involve walking down the tree, or downcasts, can only be per-
formed explicitly by means of a cast construction. The cast operator (type), which was
available in C, or the static_cast< > operator are available for this task, and are
equivalent in this case.
ᮀ Explicit Cast Constructions
Given that cabrio is again an object of the derived class PassCar, the following state-
ments
Example: Car* carPtr = &cabrio;
( (PassCar*) carPtr )->display();
first point the base class pointer carPtr to the cabrio object. carPtr is then cast as a
pointer to the derived class. This allows you to access the display() method of the
derived class PassCar via the pointer. Parentheses are necessary in this case as the

member access operator -> has a higher precedence than the cast operator (type).
The operator static_cast< > conforms to the following
Syntax: static_cast<type>(expression)
and converts the expression to the target type type. The previous example is thus equiv-
alent to
Example: static_cast<PassCar*>(carPtr)->display();
No parentheses are required here as the operators static_cast<> and -> are of equal
precedence. They are read from left to right.
After downcasting a pointer or a reference, the entire public interface of the derived
class is accessible.
ᮀ Downcast Safety Issues
Type conversions from top to bottom need to be performed with great care. Downcasting
is only safe when the object referenced by the base class pointer really is a derived class
type. This also applies to references to base classes.
To allow safe downcasting C++ introduces the concept of dynamic casting. This tech-
nique is available for polymorphic classes and will be introduced in the next chapter.
exercise
538

CHAPTER 24 TYPE CONVERSION IN CLASS HIERARCHIES
Product
PrepackedFood FreshFood

EXERCISE
Class hierarchy of products in a supermarket

×