现在的位置: 首页 > 综合 > 正文

C++中RTTI动态类型识别、静态成员、变量的四种存储方式

2013年08月24日 ⁄ 综合 ⁄ 共 2464字 ⁄ 字号 评论关闭

本文主要来讲解C++中的RTTI机制,也就是动态类型识别技术,之前我在学习《C++编程思想》的时候学习过这个技术,现在也算是复习一下吧,因为RTTI在MFC程序设计中也是有一定用处的。

 

先来看一段程序,这段程序中就是使用了RTTI,

 

执行结果如下:

Display a GIF file

 

Display a PICT file

这里最主要的函数为processFile()函数,在函数内部就是通过typeid()这个运算子来动态判断对象的类型的。

在使用RTTI技术时,要注意的是:1、需要包含头文件#include <typeinfo.h> 2、typeid()算子的参数可以是类名,也可以是对象指针。

 

好了,简单地讲了一下RTTI后,再来说一下C++中与类的静态成员相关的一些性质。

 

static 成员变量不属于对象的一部份,而是类的一部份,所以程序可以在还没有诞生任何对象的时候就处理此种成员变量。但首先你必须初始化它。

 

那么到底应该怎么初始化它呢?对于这个问题,我之前一直很困惑,知道怎么做,却不知道为什么,但是看了下面的讲解,原理就清楚了。

不要把static 成员变量的初始化动作安排在类的构造函数中,因为构造函数可能一再被调用,而变量的初值却只应该设定一次。也不要把初始化动作安排在头文件中,因为它可能会被包含许多地方,因此也就可能被执行许多次。你应该在实现文件中且类别以外的任何位置设定其初值。例如在main 之中,或全域函数中,或任何函数之外。

 

对于C++类中的静态成员变量要有这样的一个认识:静态成员变量不是类的对象所拥有的,它在类对象存在之前就已经存在,所以可以看成是一个全局的变量。

 

好,接下来再来想一下静态成员函数是怎么样的呢?

由于static 成员函数不需要借助任何对象,就可以被调用执行,所以编译器不会为它暗加一个this 指针。也因为如此,static 成员函数无法处理类别之中的non-static 成员变量。

所以,static 成员函数「没有this 参数」的这种性质,正是我们的MFC 应用程序在准备callback 函数时所需要的。

 

好了,讲完上面的这些东西,我们继续看看C++中四种变量的存储方式,如果是类对象的变量的话,就牵涉到构造函数和析构函数执行的问题。有一点很明确,一般情况下,类的对象的构造函数是从父类到子类的顺序执行的,而析构函数执行循序是恰好反过来。

 

我们先来看几个类对象变量的声明:

1、

void MyFunc()
{
 CFoo foo; // 在堆栈(stack)中产生foo 对象
 ...
}

2、

void MyFunc()
{
...
CFoo* pFoo = new CFoo(); // 在堆(heap)中产生对象
}

3、

CFoo foo; // 在任何函数范围之外做此动作

4、

void MyFunc()
{
static CFoo foo; // 在函数范围(scope)之内的一个静态对象
...
}

 

第1、2种情况是c++在堆栈(stack)、堆(heap)中分配内存时,就会隐含地调用CFoo的构造函数。

第3情况,就不一样了:由于它的声明是全局的(静态全域对象),所以它的构造式调用动作必须靠startup 码帮忙。

startup 码是什么?是更早于程序进入点(main 或WinMain)执行起来的码,由C++ 编译器提供,被联结到你的程序中。startup 码可能做些像函数库初始化、进程信息设立、I/O stream 产生等等动作,以及对static 对象的初始化动作(也就是调用其构造式)。

第4种情况:相当于(区域静态对象),类似C 语言中的静态区域变量,只会有一个实体(instance)产生,而且在固定的内存上(既不是stack 也不是heap)。它的构造式在控制权第一次移转到其声明处(也就是在MyFunc 第一次被调用)时被调用。

另外,对于以new 方式产生出来的区域对象,当对象诞生时其构造式被执行。析构式则在对象被delete 时执行。

抱歉!评论已关闭.