Run-Time Type Identification (RTTI)

Table of contents:

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;
}
 

(1)only for QObjects processed by moc

(2)If non-null, it's a valid QAbstractButton.

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



An Introduction to Design Patterns in C++ with Qt 4
An Introduction to Design Patterns in C++ with Qt 4
ISBN: 0131879057
EAN: 2147483647
Year: 2004
Pages: 268

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net