【问题标题】:Static vs dynamic type checking in C++C ++中的静态与动态类型检查
【发布时间】:2010-11-23 18:40:32
【问题描述】:

我想知道什么是静态和动态类型检查以及它们之间的区别。

【问题讨论】:

  • stackoverflow 的目标是成为所有编程知识的存储库,即使它存在于其他地方。
  • 我知道它在 google 上的某个地方,但在这里你可以得到多个定义,帮助你以更清晰的方式理解
  • @jpinto3912 rkb 是正确的......你不应该阻止人们提出这样的问题......如果它属于堆栈溢出的目标,你无权评论或反对......

标签: c++


【解决方案1】:

C++ 中有多种类型的强制转换。

最常见的是使用static_cast 将变量从一种类型的指针转​​换为另一种类型的指针。但是,您也可以使用dynamic_cast,它将检查以确保(在运行时)指针的类型正确。使用 dynamic_cast,如果指针的类型不正确,在运行时,它会返回 0。

// Assume these classes exist
// class A
// class B
// class C : B

C* c = new C();
A* a = new A();

B* b = static_cast<B*>(a); // this will work!
b = dynamic_cast<B*>(a); // b == NULL
b = dynamic_cast<B*>(c); // b is valid

【讨论】:

  • "B* b = static_cast(a); // 这会起作用!": 你不应该把它注释为“这将编译并且你得到一个非空指针; 但它不一定会起作用!”?
  • 我认为实际上 static_cast 仅适用于相关类型并且会拒绝编译,在这种情况下需要 reinterpret_cast 。这些例子在我看来都一团糟。
【解决方案2】:

C++ 对动态类型检查的支持很少。一种方法是通过dynamic_cast,另一种是通过type id。两者都只能在编译器中启用 RTTI 支持时使用。

TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);

dynamic_cast 关键字将数据从一种指针或引用类型转换为另一种,执行运行时检查以确保转换的有效性。

如果您尝试将指针转换为不是实际对象类型的类型,则转换结果将为 NULL。如果您尝试转换为对不是实际对象类型的类型的引用,则转换将引发 bad_cast 异常。

确保 Base 类中至少有一个虚函数来进行动态转换。

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

【讨论】:

  • 你没有解决静态类型检查
【解决方案3】:

假设你有:

class A {};
class B:A {};

A* a = new B();
B* b = new B();

对于静态类型,你看变量是如何声明的。

A* a = ...
B* b = ...

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

b的静态类型是B*(或者说*b的静态类型是B)。

请注意,ab 有一个静态类型,由它的声明固定 - 无论您在其中放入什么,它们都将保持相同的静态类型。 (“静态”表示“不变”)。


对于动态类型,你看看现在变量中发生了什么。

a = new B();
b = new B();

所以ab的动态类型都是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 工作)。

【讨论】:

    【解决方案4】:

    静态类型检查是在编译时完成的类型检查。这是 C++ 进行的唯一类型检查。动态类型检查是在运行时完成的类型检查。这通常出现在动态解释语言中,但在编译语言中不太常见。最后我检查了一下,C++ 不做任何类型的动态类型检查。

    编辑:显然我已经过时了。请参阅下面 Reed 的评论。

    【讨论】:

    • dynamic_cast 存在于 C++ 中,并在许多 C++ 运行时进行运行时类型检查。
    【解决方案5】:

    静态类型检查意味着类型检查发生在编译时。在这种情况下,运行时不使用类型信息。

    在运行时使用类型信息时会发生动态类型检查。 C++ 使用一种称为 RTTI(运行时类型信息)的机制来实现这一点。使用 RTTI 的最常见示例是 dynamic_cast 运算符,它允许向下转换多态类型:

    // assuming that Circle derives from Shape...
    Shape *shape = new Circle(50);
    Circle *circle = dynamic_cast<Circle*> shape;
    

    此外,您可以使用 typeid 运算符来了解对象的运行时类型。例如,您可以使用它来检查示例中的形状是圆形还是矩形。这是一些further information

    【讨论】:

    • 值得注意的是,在上面的简单示例中,static_cast 完全有效。仅当您不确定 shape 是 Circle 类型时才应使用 dynamic_cast,在这种情况下 dynamic_cast 将返回 NULL(或者如果您正在投射引用,则抛出异常)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2013-09-14
    • 2021-04-07
    • 2011-01-17
    相关资源
    最近更新 更多