RUNTIME_CLASS
RUNTIME_CLASS
RUNTIME_CLASS( class_name )
【参数】
class_name:类的实际名字(不用引号括起来)。
【说明】
利用这个宏通过C++类的名字获得一个运行时类结构。
RUNTIME_CLASS为class_name指定的类返回一个指向CRuntimeClass结构的指针。只有用DECLARE_DYNAMIC,DECLARE_DYNCREATE或DECLARE_SERIAL定义的CObject的派生类才能返回CRuntimeClass结构指针。更多的信息参见“Visual C++程序员指南”中的“CObject类”主题。
【示例】
// RUNTIME_CLASS的例子
CRuntimeClass* prt = RUNTIME_CLASS( CAge );
ASSERT( lstrcmp( prt->m_lpszClassName, "CAge" ) == 0 );
学MFC学到文档,视图和框架的时候,明白必需在这三个类的派生类的类声明里加上DECLARE_DYNCREATE,然后在类声明外合适的地方加上IMPLEMENT_DYNCREATE,然后文档,视图和框架,还有文档模板就能够协调务工了。查看MSDN,发现类似的宏有这几对:
DECLARE_DYNAMIC 和 IMPLEMENT_DYNAMIC
DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE
DECLARE_SERIAL 和 IMPLEMENT_SERIAL
虽然MSDN里介绍了它们的功能,但对于它们为啥会起那样的功能心里却没底,于是翻了翻MFC的源代码Code,喜爱钻牛角尖的人能够和我一起来钻一钻。
1. RUNTIME_CLASS宏定义
#define RUNTIME_CLASS(class_name)
((CRuntimeClass*)(&class_name::class##class_name))
其中##的意思是把##两边的符号都停止宏扩展(假如它们是宏的话),然后把扩展后的内容连接在一起,中间不加空格。例如:RUNTIME_CLASS(CView)将被扩展成:
(CRuntimeClass*)(&CView::classCView)
但那个classCView是什么意思?原来,classCView是由DECLARE_DYNAMIC(CView)引入的唯一public属性的CRuntimeClass类别的静态成员变量:
static const AFX_DATA CRuntimeClass classCView;
原来RUNTIME_CLASS的功能就引用由DECLARE_DYNAMIC宏引入的静态成员变量。
2. DECLARE_DYNAMIC(class_name)
由于篇幅理由,宏的具体定义代码Code就不列出来了,感兴趣的能够去看文档afx.h。
该宏往类中声明了三个成员:
protected:
static CRuntimeClass* PASCAL _GetBaseClass();
public:
virtual CRuntimeClass* GetRuntimeClass() const;
static const AFX_DATA CRuntimeClass class##class_name;
有两个成员参数,唯一静态成员变量class+类名,同RUNTIME_CLASS相似,如果是DECLARE_DYNAMIC(CView)的话,那个静态成员变量将是classCView。可见这个成员变量的名字是和DECLARE_DYNAMIC的参数parameter有关的。在下文把那个成员变量统统记做class##class_name。
那个静态成员和两个成员参数在哪里被初始化和具体呈现呢?原来是在IMPLEMENT_DYNAMIC宏里。
3. IMPLEMENT_DYNAMIC(class_name, base_class_name)
查看它的宏定义,假如_AFXDLL被定义了的话,由DECLARE_DYNAMIC引入的成员的初始化和呈现是那样的:
CRuntimeClass* PASCAL class_name::_GetBaseClass()
{
return RUNTIME_CLASS(base_class_name);
}
CRuntimeClass* class_name::GetRuntimeClass() const
{
return RUNTIME_CLASS(class_name);
}
AFX_COMDAT const AFX_DATADEF
CRuntimeClass class_name::class##class_name =
{
#class_name,
sizeof(class class_name),
0xFFFF,
NULL,
NULL,
&class_name::_GetBaseClass,
NULL
};//这是在初始化静态成员变量class##class_name。
//CRuntimeClass框架的各个成员的意义可查看msdn。
4. _DECLARE_DYNAMIC(class_name)
该宏的定义和DECLARE_DYNAMIC(class_name)基本相同。不相同之处是静态成员class##class_name前面没有const修饰符。
5. DECLARE_DYNCREATE(class_name)
该宏也往类中引入了DECLARE_DYNAMIC宏所引入的那三个成员。除此之外,它还另外引入唯一成员:
static CObject* PASCAL CreateObject();
该宏引入的成员在IMPLEMENT_DYNCREATE里初始化和呈现。
6. IMPLEMENT_DYNCREATE(class_name, base_class_name)
该宏自然是初始化和呈现由DECLARE_DYNCREATE引入的成员了。
咱们看看CreateObject的呈现:
CObject* PASCAL class_name::CreateObject()
{
{
return new class_name;
}
参数是如此简单,它就用CObject类里重载的new操作符创建唯一该类类别的对象。
7. _DECLARE_DYNCREATE(class_name)
该宏引入了和DECLARE_DYNCREATE引入的四个成员差不多的成员。唯一的区别是该宏引入的静态成员class##class_name前面没有const修饰符。
8. DECLARE_SERIAL(class_name)
该宏引入了和_DECLARE_DYNCREATE所引入的相同的四个成员,另外它还多了这么一句:
AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);
原来是把重载操作符operator>>的参数当作该类的友元。于是在操作符参数operator>>中就能够来访该类的成员了。
9. IMPLEMENT_SERIAL(class_name, base_class_name, wSchema)
该宏初始化了成员变量:
CRuntimeClass class_name::class##class_name=
{
#class_name,
sizeof(class class_name),
wSchema,
class_name::CreateObject),
RUNTIME_CLASS(base_class_name),
NULL
};//在那里,class##class_name前面是没有const修饰符的。
该宏还呈现了下列参数:
CObject* PASCAL class_name::CreateObject()
{
return new class_name;
}
CRuntimeClass* class_name::GetRuntimeClass() const
{
return RUNTIME_CLASS(class_name);
}
CArchive& AFXAPI operator>>
(CArchive& ar, class_name* &pOb)
{
pOb=(class_name*)ar.ReadObject(RUNTIME_CLASS(class_name));
return ar;
}
该宏还声明了唯一参数原型:
AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name));
RUNTIME_CLASS相关推荐
- 最最基本的框架宏使用RUNTIME_CLASS DECLARE_DYNAMIC IMPLEMENT_RUNTIMECLASS
Demo.h // 简化封装 // 部分的内容在MFC中都是固化的,所以理解并加以记忆是必要的 // #pragma once #include <windows.h>/// // 调试支 ...
- MFC-4简单的窗口重绘(非部分重绘)
#include <afxwin.h> #include "resource.h" #include <afxtempl.h> //定义模板类的头文件cla ...
- vs2008中,在OCX控件中应用doc/view基本步骤
1.利用向导创建一个MFC ActiveX Control控件CMyOCX: 2.在工程中加入ActivDoc头文件和执行文件: class CActiveXDocTemplate : public ...
- 在对话框中应用CScrollView显示图像
1.用vs2008创建一个基于对话框的工程DialogView: 2.添加一个新类CMyDocument,基类为CDocument: 3.添加一个新类CMyView,基类为CScrollView: 4 ...
- VC 文件操作(文件查找,打开/保存,读/写,复制/删除/重命名)
右击项目->属性->字符集:使用多字节字符集. 这样可以使用char到CString的转化. char sRead[20] = ""; CString strtest ...
- JAVA实现中点画线_实验1-中点画线和Bresenham画线算法的实现
<实验1-中点画线和Bresenham画线算法的实现>由会员分享,可在线阅读,更多相关<实验1-中点画线和Bresenham画线算法的实现(9页珍藏版)>请在人人文库网上搜索. ...
- mfc只有doc才能序列化吗_MFC序列化-IMPLEMENT_SERIAL(...)
MFC源码:#define DECLARE_DYNAMIC(class_name) \public: \static const CRuntimeClass class##class_name; \v ...
- mfc cedit 默认显示内容_VS2013/MFC编程学习(一)
一.前言 1.1 VC++简介 VC++全称是Visual C++,是由微软提供的C++开发工具,它与C++的根本区别就在于,C++是语言,而VC++是用C++语言编写程序的工具平台.VC++不仅是一 ...
- VC中DDX/DDV自定义
DDX用于控件与变量的数据交换.DDV用于对数据交换后的变量进行校验,倘若校验失败将抛出异常导致Updata后面部分不能正常执行.必要时需要对Updata的返回值进行判断. 对于数据交换,需要 ...
最新文章
- 招募100名科研人,念出书中内容即可,300元/小时,无经验要求!
- 前沿速递:Maven中央仓库新增依赖漏洞提醒功能
- 数据结构与算法 / LRU 缓存淘汰算法
- python读写excel模块pandas_Python3使用pandas模块读写excel操作示例
- 同软件多个线程设置不同ip_多线程--面试知识
- linux下带.d的文件夹,linux – 如何在shell脚本中包含目录中的所有文件(在本例中为/etc/init.d/iptables)...
- 知识库如何跟其他业务系统结合
- Linux|麒麟操作系统实现多路RTMP|RTSP播放
- java连接kafka接收不到数据_Kafka客户端无法接收消息
- 入门 | 从文本处理到自动驾驶:机器学习最常用的50大免费数据集
- win7系统两台计算机共享文件,教你设置win7系统的两台电脑实现文件共享的详细步骤...
- Cypress使用教程
- 一生之书《悉达多》接受这个世界,爱它,属于它
- 邮件服务器需要445端口,445端口是什么服务端口(2)
- 微信新表情真的太骚了!!
- mahout第一篇-----Mahout学习路线图
- SiteSucker
- r329开发板部署aipu模型
- 输出pdf文件的一个简单方法
- 日报2015/11/17(第一行代码读书笔记)