定时器的使用
来源:互联网 发布:java执行adb命令 编辑:程序博客网 时间:2024/05/17 03:33
VC++实现非窗口类中使用定时器的方法(图)
图一、定时器界面效果图
一、实现方法
在非窗口类中使用定时器,需要了解的知识比较多。首先非窗口类中没有消息映射,也没有象CWnd类具有的SetTimer()方法来设置定时器。没有消息映射,就只能靠我们自己定义的回调函数来处理定时器的消息,因此大家有必要了解一下回调函数的概念。因为回调函数只能用全局函数或者静态成员函数来实现,而为了维持类的完整性,又要求使用类的静态成员函数来作为回调函数,所以我们又需要了解一下静态数据成员和静态成员函数的性质。又因为定时器是在我们的程序中产生的,这又需要来管理定时器,所以又用到了映射表类CMap,因此介绍一下CMap的简单用法也是必不可少的。
所谓回调函数就是按照一定的形式由开发人员定义并编写实现内容,当发生某种事件时由系统或其它函数来调用的函数。使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己编写的一个函数(也就是回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,也就是某种事情发生的时候,利用传递的函数地址调用回调函数,这时开发人员可以利用这个机会在回调函数中处理消息或完成一定的操作。回调函数只能是全局函数,或者是静态函数,因为这个函数只是在类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。
在C语言中,声明一个数据为静态类型,意味着该变量的生存周期是静态的,即在程序的开始时即分配,到程序终止时才释放。但在C++中,声明一个类中的成员为静态类型,则意味着该类的所有实例只有该成员的一个拷贝。也就是说,不管应用程序中创建了这个类的多少个对象,其静态成员只有一个副本,该副本为这个类的所有对象实例所共享,而对于非静态成员,每个类对象实例都有自己的拷贝。例如一个公司职员类的定义如下:
class CPerson
{
public:
CString szName;
static CString szCompanyName;
CPerson();
virtual ~CPerson();
};
对于同一家公司员工,每个人都有不同的姓名,但是他们的公司名字是一样的,所以就可以用一个静态类型来保存,这样所有的员工都共享这个公司名称,只要一位员工更新了公司名称,则所有员工的公司名称就被更新了。
静态成员被当作该类类型的全局对象,可以把一个静态数据成员和静态成员函数当成全局变量和函数那样去存储和访问,但又被隐藏在类的内部,并且清楚地与这个类相联系但又不是全局对象,同全局对象相比,使用静态成员有两个优势:
(1) 静态成员没有进入程序的全局名字空间,它属于类,它的名字只在类的范围内有效,因此不存在与程序中其他全局名字冲突的可能性。
(2) 可以实现信息隐藏,并可以保持类的完整性,可以是private(私有的)成员、public(公有的)成员或者protected(保护的)成员,而全局对象不能。
使用静态数据成员可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,就可以保证所有对象都能够访问到被更新后的值,这样可以提高效率和节省内存空间。
在类中将一个成员变量声明为静态的,与声明普通变量的唯一区别就是在其定义前加一个static,象上面的例子中那样声明:static CString szCompanyName;静态数据成员显式初始化与一般数据成员初始化不同。静态数据成员显式初始化的格式如下:
<数据类型><类名>::<静态数据成员名>=<值>
对于上面的例子这样初始化:CString CPerson::szCommpanyName = "天极网";
这表明:
(1) 初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆。
(2) 初始化时不加该成员的访问权限控制符private,public等。
(3) 初始化时使用作用域运算符来标明它所属类,因此,静态数据成员是类的成员,而不是对象的成员。
在类的成员函数中可以直接引用该类的静态数据成员,而不必使用成员访问操作符。但是在非成员函数中,我们必须以两种方式之一访问静态数据成员。
(1) 使用成员访问操作符。
例如:me是CPerson的一个实例,在非成员函数中可以这样应用其中的静态数据成员:CString TheCommpanyName = me.CommpanyName;
(2) 因为类静态数据成员只有一个拷贝,所以它不一定要通过对象或者指针来访问。方法二就是用被类名限定修饰的名字直接访问它。当我们不通过类的成员访问操作符访问静态数据成员时,必须指定类名以及紧跟其后的域操作符,因为静态成员不是全局对象,所以我们不能在全局域中找到它。如:CString TheCommpanyName = CPerson::CommpanyName;
顺便说一句静态数据成员还有两个特点:一是静态数据成员的类型可以是其所属类,而非静态数据成员只能被声明为该类的对象的指针或引用;二是静态数据成员可以被作为类成员函数的缺省实参,而非静态成员不能。
静态成员函数的声明与普通函数的唯一区别就是在前面加一个static。通常,当前对象的地址(this)是被隐含地传递到被调用的非静态成员函数的。静态成员函数具有类的范围,同非静态成员函数相比,静态成员函数没有this参数,因此它不能访问一般的数据成员,而只能访问静态数据成员、枚举或嵌套类型和其他的静态成员函数。这样使用静态成员函数在速度上可以比全局函数有少许的增长,它不仅没有传递this指针所需的额外的花费,而且还有使函数在类内的好处。如果静态成员函数中要引用非静态成员时,可通过对象来引用。我们可以用成员访问操作符点(.)和箭头(->)为一个类对象或指向类对象的指针访问静态成员函数,也可以用限定修饰名直接访问静态成员函数,而无需声明类对象。
静态成员函数遵循约束条件如下:(1) 不能用成员选择符(.或->)访问非静态成员;(2) 不能说明为虚函数;(3) 不能与有相同参数类型的非静态成员函同名;(4) 不能声明为const或volatile;(5) 出现在类体外的函数定义不指定关键字static。
映射表类(CMap)是MFC集合类中的一个模板类,也称作为"字典",就像一种只有两列的表格,一列是关键字,一列是数据项,它们是一一对应的。关键字是唯一的,给出一个关键字,映射表类会很快找到对应的数据项。映射表的查找是以哈希表的方式进行的,因此在映射表中查找数值项的速度很快。举个例子来说吧,公司的所有职员都有一个工号和自己的姓名,工号就是姓名的关键字,给出一个工号,就可以很快的找到相应的姓名。映射类最适用于需要根据关键字进行快速检索的场合,我们的程序中就用映射表来保存计时器标志值和类实例指针,用计时器的标志值作为关键字。
从上面的叙述可以看出来,在类中静态成员函数只能引用静态数据成员和静态成员函数,如何才能让静态成员函数也能引用非静态的成员函数和成员变量呢?这也是我们后面将会用到的。
分析一下静态成员函数和非静态成员函数的区别,我们会发现非静态成员函数之所以能访问所有的成员函数和成员变量,是因为它有个隐含的参数this,访问成员函数和成员变量的时候,实际上是在前面添加了个引用的符号"this->",所以我们就可以试着将this这个指针作为静态成员函数的一个参数传递进去,这样不就可以在静态成员函数中访问所有的成员函数和成员变量了吗?下面给出一个实现的例子:
- 定时器的使用
- C#定时器的使用
- C#定时器的使用
- java定时器的使用
- 内核定时器的使用
- 定时器的使用
- linux定时器的使用
- linux定时器的使用
- linux定时器的使用
- linux定时器的使用
- 定时器的使用
- C#定时器的使用
- 内核定时器的使用
- 使用glib的定时器
- Linux定时器的使用
- linux定时器的使用
- 定时器的使用
- timer 定时器的使用
- 一位计算机类的大三计算机学生致全国大学生联合抵制腾讯QQ霸权行为的一封建议书
- 98年最后一道高数题
- 在字符串的任意位置插入另一指定字符串
- 一步步制作真彩工具条
- 高级查询实例
- 定时器的使用
- 关于QQ和360去留的问题
- 使用定时器3
- 遇见裸女,不围观、不拍照也是一种善良
- 关于调试的一点技巧
- Scala And XML
- 定时器的使用2
- JQuery ajax
- 函数调用方式(__cdecl, _stdcall, _fastcall, _thiscall, etc)