This section covers dynamic_cast and typeid, two operators that enable runtime type identification (RTTI).
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.
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.
RTTI allows 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, then a null pointer is returned.
dynamic_cast performs runtime checking to determine whether the pointer/ reference conversion is valid.
Example 19.6 shows operations on a collection of QWidgets. In fact, we wish to operate only buttons and sliders, leaving the rest alone.
Example 19.6. src/rtti/dynamic_cast.cpp
[ . . . . ] int processWidget(QWidget* wid) { if (widpointer->inherits("QAbstractSpinBox")) { <-- 1 QAbstractSpinBox* qasbp = static_cast (widpointer); qasbp->setAlignment(Qt::AlignHCenter); } else { QAbstractButton* buttonPtr = dynamic_cast(widpointer); if (buttonPtr) { <-- 2 buttonPtr->click(); qDebug() << QString("I clicked on the %1 button:") .arg(buttonPtr->text()); } return 1; } return 0; } [ . . . . ] QVector 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; }
|
qobject_cast (see Section 15.3) is faster than dynamic_cast, but only works on QObject-derived types. |
In terms of run-time 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 very different situations.
19.8.1. typeid Operator
Another operator that is part of RTTI is typeid(), which returns type information about its argument. For example:
void f(Person& pRef) { if(typeid(pRef) == typeid(Student) { // pRef is actually a reference to a Student object. // Proceed with Student specific processing. } else { // The Object referred to by pRef is not a Student. // Do whatever alternative stuff is required. } }
typeid() returns a type_info object that corresponds to the argument's type.
If two objects are the same type, their type_info objects should be equal. The typeid() operator can be used for polymorphic types or non-polymorphic types. It can also be used on basic types as well as custom classes. Furthermore, the arguments to typeid() can be type names or object names.
This is one possible implementation of the type_info class.
class type_info { private: type_info(const type_info& ); // cannot be copied by users type_info& operator=(const type_info&); // implementation dependent representation public: virtual ~type_info(); bool operator==(const type_info&) const; bool operator!=(const type_info&) const; bool before(const type_info& rhs) const; const char* name() const; // returns a pointer to the name of the type }
Member Selection Operators |
Part I: Introduction to C++ and Qt 4
C++ Introduction
Classes
Introduction to Qt
Lists
Functions
Inheritance and Polymorphism
Part II: Higher-Level Programming
Libraries
Introduction to Design Patterns
QObject
Generics and Containers
Qt GUI Widgets
Concurrency
Validation and Regular Expressions
Parsing XML
Meta Objects, Properties, and Reflective Programming
More Design Patterns
Models and Views
Qt SQL Classes
Part III: C++ Language Reference
Types and Expressions
Scope and Storage Class
Statements and Control Structures
Memory Access
Chapter Summary
Inheritance in Detail
Miscellaneous Topics
Part IV: Programming Assignments
MP3 Jukebox Assignments
Part V: Appendices
MP3 Jukebox Assignments
Bibliography
MP3 Jukebox Assignments