[ fromfile: rtti.xml id: rtti ]
Abstract
This section covers dynamic_cast
and typeid
, two operators that enable runtime type identification (RTTI).
The conversion of a base class pointer to a derived class pointer is called downcasting because casting from the base class to a derived class is considered moving down the class hierarchy.
When operating on hierarchies of types, sometimes it is necessary to downcast a pointer to a more specific type. Without a downcast, only the interface of the pointer type (the base class) is available. One common situation where downcasting is used is inside functions that accept base class pointers.
RTTI enables programmers to safely convert pointers and references to objects from base to derived types.
dynamic_cast<D*>(ptr)
takes two operands: a pointer type D*
and a pointer ptr
of a polymorphic type B*
.
If D
is a base class of B
(or if B
is the same as D
) dynamic_cast<D*>(ptr)
is an upcast (or not a cast at all) and is equivalent to static_cast<D*>(ptr)
.
But if ptr
has the address of an object of type D
, where D
is derived from B
, the operator returns a downcast pointer of type D*
, pointing to the same object.
If the cast is not possible, a null pointer is returned.
dynamic_cast
performs runtime checking to determine whether the pointer/reference conversion is valid.
For example, suppose you are processing a collection of QWidget*
.
Example 19.23 shows operations on a collection of QWidget
s. Further suppose that you want to operate only on buttons and spinboxes, leaving the other widgets alone.
Example 19.23. src/rtti/dynamic_cast.cpp
[ . . . . ] int processWidget(QWidget* wid) { if (wid->inherits("QAbstractSpinBox")) { QAbstractSpinBox* qasbp = static_cast <QAbstractSpinBox*> (wid); qasbp->setAlignment(Qt::AlignHCenter); } else { QAbstractButton* buttonPtr = dynamic_cast<QAbstractButton*>(wid); if (buttonPtr) { buttonPtr->click(); qDebug() << QString("I clicked on the %1 button:") .arg(buttonPtr->text()); } return 1; } return 0; } [ . . . . ] QVector<QWidget*> widvect; widvect.append(new QPushButton("Ok")); widvect.append(new QCheckBox("Checked")); widvect.append(new QComboBox()); widvect.append(new QMenuBar()); widvect.append(new QCheckBox("With Fries")); widvect.append(new QPushButton("Nooo!!!!")); widvect.append(new QDateTimeEdit()); widvect.append(new QDoubleSpinBox()); foreach (QWidget* widpointer, widvect) { processWidget(widpointer); } return 0; }
<include src="src/rtti/dynamic_cast.cpp" href="src/rtti/dynamic_cast.cpp" id="dynamiccastcpp" mode="cpp"/>
Note | |
---|---|
|
In terms of runtime cost, dynamic_cast
is considerably more expensive, perhaps 10 to 50 times the cost of a static_cast
. However, they are not interchangable operations and are used in different situations.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |