Voi*_*ter 17
静态类型检查意味着在编译时进行类型检查.在这种情况下,在运行时不使用类型信息.
在运行时使用类型信息时会发生动态类型检查.C++使用一种称为RTTI(运行时类型信息)的机制来实现它.使用RTTI的最常见示例是dynamic_cast运算符,它允许向下转换多态类型:
// assuming that Circle derives from Shape...
Shape *shape = new Circle(50);
Circle *circle = dynamic_cast<Circle*> shape;
Run Code Online (Sandbox Code Playgroud)
此外,您可以使用typeid运算符来查找对象的运行时类型.例如,您可以使用它来检查示例中的形状是圆形还是矩形.这是一些进一步的信息.
假设您有:
class A {};
class B:A {};
A* a = new B();
B* b = new B();
Run Code Online (Sandbox Code Playgroud)
对于静态类型,您查看变量是如何声明的。
A* a = ...
B* b = ...
Run Code Online (Sandbox Code Playgroud)
所以 的静态类型a是A*(或者换句话说, 的静态类型*a是A)。
b而is的静态类型B*(或者换句话说,*bis 的静态类型B)。
请注意,aandb具有由其声明固定的静态类型 - 无论您在其中放入什么内容,它们都会保持相同的静态类型。(“静态”意味着“不变”)。
对于动态类型,您可以查看变量中现在发生的情况。
a = new B();
b = new B();
Run Code Online (Sandbox Code Playgroud)
a因此和 的动态类型b都是B*(或者换句话说,*a和 的动态类型*b都是B)。
请注意,动态类型可以更改 - 如果您这样做,那么a = new A()它们的动态类型a就会更改为A*。有时您不知道动态类型是什么 - 例如,如果您知道,那么a = somefunc()可能a有动态类型A*,B*甚至C*(如果您没有见过的某些代码定义为或 的C子类)。AB
如果A有一个virtual方法,那么您可以用来dynamic_cast找出动态类型是什么。(通常,如果您使用此类代码,您希望能够执行此操作delete a;要使其工作A,析构函数必须是virtual。并且使A析构函数成为虚拟就足以dynamic_cast工作)。
C++ 对动态类型检查的支持很少,一种是通过dynamic_cast,另一种是通过type id 。两者都只能在编译器中启用 RTTI 支持时使用。
TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);
Run Code Online (Sandbox Code Playgroud)
dynamic_cast 关键字将数据从一个指针或引用类型转换为另一种,执行运行时检查以确保转换的有效性。
如果您尝试强制转换为指向不是实际对象类型的类型的指针,则强制转换的结果将为 NULL。如果您尝试强制转换为对不是实际对象类型的类型的引用,则该类型转换将抛出 bad_cast 异常。
确保 Base 类中至少有一个虚函数来使 dynamicast 工作。
// expre_typeid_Operator.cpp
// compile with: /GR /EHsc
#include <iostream>
#include <typeinfo.h>
class Base {
public:
virtual void vvfunc() {}
};
class Derived : public Base {};
using namespace std;
int main() {
Derived* pd = new Derived;
Base* pb = pd;
cout << typeid( pb ).name() << endl; //prints "class Base *"
cout << typeid( *pb ).name() << endl; //prints "class Derived"
cout << typeid( pd ).name() << endl; //prints "class Derived *"
cout << typeid( *pd ).name() << endl; //prints "class Derived"
delete pd;
}
Run Code Online (Sandbox Code Playgroud)