C++中的静态与动态类型检查

rkb*_*rkb 11 c++

我想知道什么是静态和动态类型检查以及它们之间的差异.

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运算符来查找对象的运行时类型.例如,您可以使用它来检查示例中的形状是圆形还是矩形.这是一些进一步的信息.

  • 值得注意的是,static_cast在上面的简单示例中完全有效.只有在您不确定形状是Circle类型时才应使用dynamic_cast,在这种情况下,dynamic_cast将返回NULL(如果您正在转换引用,则抛出异常). (5认同)

use*_*876 6

假设您有:

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)

所以 的静态类型aA*(或者换句话说, 的静态类型*aA)。

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工作)。


yes*_*aaj 5

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)