c++rtti(crt体雕术)

简介:

在 C++ 中,RTTI(Run-time type identification)是一种机制,它允许程序在运行时确定对象类型。RTTI 是由编译器提供的,因此它是与平台无关的。C++ 中的 RTTI 还提供了向上转换和向下转换两种操作。

多级标题:

一级标题:什么是 RTTI?

二级标题:C++ 中的什么对象可以进行 RTTI 操作?

三级标题:实现 RTTI 操作的关键字

四级标题:向上转换和向下转换操作

内容详细说明:

一级标题:什么是 RTTI?

根据 C++ 官方文档的定义,Run-time type identification(运行时类型识别)是一个 C++ 机制,它允许程序在运行时确定一个对象的类型。这在许多情况下非常有用。例如,当我们需要知道一个对象是哪种类型时,可以使用 RTTI 操作。

二级标题:C++ 中的什么对象可以进行 RTTI 操作?

C++ 中的普通类、结构体和联合体对象都可以进行 RTTI 操作。C++ 中的 RTTI 操作还提供了向上转换和向下转换等操作。

三级标题:实现 RTTI 操作的关键字

从语言层面来实现 RTTI 操作主要有两个关键字:typeid 和 dynamic_cast。这里我们介绍一下这两个关键字。

1. typeid:这个操作符接受一个表达式作为其操作数,并返回该表达式的类型信息对象,该类型信息对象可以用来比较两个表达式的类型是否相同。

例如:

```

#include

#include

using namespace std;

class A {

public:

virtual void foo(){}

};

class B : public A {};

int main() {

A *pA = new B;

cout<

return 0;

```

这段代码中,在对 A 类型指针进行 * 操作符操作后,typeid 操作符会返回 pA 指向的对象的类型信息对象,并使用 name() 函数返回该类型的名称。

2. dynamic_cast:这个运算符可将指向一个基类对象的指针或引用安全地转换成指向派生类子对象的指针或引用,当转换失败时,会返回一个 null 指针。

例如:

```

#include

#include

using namespace std;

class A {

public:

virtual void foo(){}

};

class B : public A {};

class C : public A {};

int main() {

A *pA = new B;

B *pB = dynamic_cast(pA);

if(pB)

cout<<"pA指向了B类型的对象"<

C *pC = dynamic_cast(pA);

if(!pC)

cout<<"pA并不指向C类型的对象"<

return 0;

```

这段代码中,我们将一个 A 类型指针转换成了 B 类型指针。因为我们已将指针指向了 B 类型的对象,所以转换成功。但是我们将其转换成 C 类型指针时,因为实际对象类型并不是 C 类型,所以转换失败。

四级标题:向上转换和向下转换操作

向上转换和向下转换是 RTTI 操作中比较常见的两个操作,下面我们来详细介绍一下:

1. 向上转换:当子类对象赋给基类指针时,编译器会进行自动向上转型,这个过程中会发生截取精度的现象,也就是只能访问到基类中的公有成员,而不能访问到子类中特有的成员。

例如:

```

#include

using namespace std;

class A {

public:

int x;

void func(){}

};

class B : public A {

public:

int y;

};

int main() {

B b;

A *pA = &b;

pA->x = 10;

//pA->y = 20;编译器会报错

return 0;

```

这段代码中,我们定义了两个类 A 和 B,B 是 A 的子类。在主函数中,我们将 b 对象的地址、也就是子类的地址,赋值给了 A 类型的指针 pA。在使用 pA 指针访问 x 变量时,是不会有问题的,但是使用 pA 指向的对象并不能访问 y 变量。

2. 向下转换:当基类指针赋给子类指针(如果不能转换,返回空指针)时,需要使用 dynamic_cast 进行转换操作。

例如:

```

#include

using namespace std;

class A {

public:

int x;

virtual void func(){}

};

class B : public A {

public:

int y;

void func(){}

};

int main() {

A *pA = new B;

B *pB = dynamic_cast(pA);

pB->y = 10;

pB->x = 20;

return 0;

```

这段代码中,我们定义了两个类 A 和 B,B 是 A 的子类。在主函数中,我们将 B 类型指针转换成 A 类型指针,然后又使用 dynamic_cast 进行了向下转换,使得 B 类型指针可以访问 B 类型对象中的成员变量。