标准C++的一个新特征是RTTI(Run-Time Type Information运行时类型信息),它为程序在运行时确定对象类型,提供了一种标准方法。
在标准C++中,有三个支持RTTI的元素:
1. 关键字dynamic_cast(动态强制转换):操作符dynamic_cast将一个指向基类的指针或者引用转换为一个指向派生类的指针或引用
(如果不能正确转换,则返回0——空指针),格式为:
dynamic_cast < type-id > (exp )
dynamic_cast在转化过程中要用到相关类的类型信息类type_info中的信息。
说明:
(a).如果exp的真实类型是type-id则转换成功;否则转换失败;
(b)在转换失败时,指针类型和引用类型是有区分:
i. 若exp和type-id都是指针类型,转换是失败返回0;
ii. 若exp和type-id都是引用类型,则抛出bad_cast 异常;
//这一点也说明了指针与引用是有区别的!
2. 关键字typeid(类型标识符):用来检测类型(返回type_info类对象的的引用),
格式为:typeid ( exp ) 或 typeid ( type-id )
其中,exp结果为对象的表达式,type-id为类名。
说明: typeid只有作用于类类型时,RTTI的特性才能显现,否则,其他类型都是静态编译时确定的。
把typeid作用于指针的解引用*p时,若指针p为0,则:如果p指向的类型是带虚函数的类类型,
则typeid(*p)在运行时抛出一个bad_typeid异常;
3. 类type_info(类型信息):存储特定类型的有关信息,定义在<typeinfo>头文件中。
type_info类的具体内容由编译器实现来决定,但是至少必须包含返回字符串的name()成员函数。
程序举例:
#include <iostream>
#include <typeinfo> //for 'typeid'
using namespace std;
class Person {
public:
// ... Person members ...
virtual ~Person() {}
};
class Employee : public Person {
// ... Employee members ...
};
int main()
{
Person person;
Employee employee;
Person *ptr = &employee;
Person &ref = employee;
// The string returned by typeid::name is implementation-defined
std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time)
std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time)
std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time)
std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time
// because it is the dereference of a
// pointer to a polymorphic class)
std::cout << typeid(ref).name() << std::endl; // Employee (references can also be polymorphic)
Person* p = 0;
try {
typeid(*p); // not undefined behavior; throws std::bad_typeid
// *p, *(p), *((p)), etc. all behave identically
}catch (...){
cout << "NULL pointer!"<<endl;
}
Person& pRef = *p; // undefined behavior, dereferences null
typeid(pRef); // does not meet requirements to throw std::bad_typeid
Employee e;
Person pp;
Person &per_ref = pp;
try{
Employee & em_ref = dynamic_cast<Employee&>(per_ref);
}catch(bad_cast e){
cout << "bad cast : not valid type reference !" <<endl;
}catch(...){
cout << "not valid type reference !" <<endl;
} // because the expression for typeid is not the result
// of applying the unary * operator; behavior is undefined
}
t1 == t2 | 如果两个对象t1和t2类型相同,则返回true;否则返回false |
t1 != t2 | 如果两个对象t1和t2类型不同,则返回true;否则返回false |
t.name() | 返回类型的C-style字符串,类型名字用系统相关的方法产生 |
t1.before(t2) | 返回指出t1是否出现在t2之前的bool值 |
|
在MinGW2.05下的运行结果: |
[2] Thinking in C++(Edition 2)
[3] International Standard:ISO/IEC 14882:1998
In C++, the typeid
keyword is used to determine the class of an object at run time. It returns a reference to std::type_info
object, which exists until the end of the program[1]. The use of typeid
is often preferred over dynamic_cast<class_type>
in situations where just the class information is needed, because typeid
is a constant-time procedure, whereas dynamic_cast
must traverse the class derivation lattice of its argument at runtime. Some aspects of the returned object are implementation-defined, such as std::type_info::name()
, and cannot be relied on across compilers to be consistent.
Objects of class std::bad_typeid
are thrown when the expression for typeid
is the result of applying the unary * operator on a null pointer. In other words, the expression must take the form typeid(*p)
where p
is any expression resulting in a null pointer.
From Wikipedia, the free encyclopedia:
Run-time type information
In computer programming, RTTI (Run-Time Type Information, or Run-Time Type Identification) refers to a C++ mechanism that exposes information about an object'sdata type at runtime. Run-time type information can apply to simple data types, such as integers and characters, or to generic types. This is a C++ specialization of a more general concept called type introspection.
In the original C++ design, Bjarne Stroustrup did not include run-time type information, because he thought this mechanism was frequently misused.[1]
Contents[hide] |
[edit]Features
The dynamic_cast<>
operation and typeid
operator in C++ are part of RTTI.
The C++ run-time type information permits performing safe typecasts and manipulate type information at run time.
RTTI is available only for classes which are polymorphic, which means they have at least one virtual method. In practice, this is not a limitation because base classes must have a virtual destructor to allow objects of derived classes to perform proper cleanup if they are deleted from a base pointer.
RTTI is optional with some compilers; the programmer can choose at compile time whether to include the function. There may be a resource cost to making RTTI available even if the program does not use it.
[edit]C++ Example
/* A base class pointer can point to objects of any class which is derived * from it. RTTI is useful to identify which type (derived class) of object is * pointed to by a base class pointer. */ #include <iostream> class abc // base class { public: virtual ~abc() { } virtual void hello() { std::cout << "in abc"; } }; class xyz : public abc { public: void hello() { std::cout << "in xyz"; } }; int main() { abc *abc_pointer = new xyz(); xyz *xyz_pointer; // to find whether abc_pointer is pointing to xyz type of object xyz_pointer = dynamic_cast<xyz*>(abc_pointer); if (xyz_pointer != NULL) { std::cout << "abc_pointer is pointing to a xyz class object"; // identified } else { std::cout << "abc_pointer is NOT pointing to a xyz class object"; } // needs virtual destructor delete abc_pointer; return 0; }
An instance where RTTI is used is illustrated below:
class base { public: virtual ~base(){} }; class derived : public base { public: virtual ~derived(){} int compare (derived &ref); }; int my_comparison_method_for_generic_sort (base &ref1, base &ref2) { derived & d = dynamic_cast<derived &>(ref1); // RTTI used here // RTTI enables the process to throw a bad_cast exception // if the cast is not successful return d.compare (dynamic_cast<derived &>(ref2)); }
[edit]See also
[edit]References
- ^ Bjarne Stroustrup. "A History of C++: 1979—1991". p. 50. Retrieved 2009-05-18.