运行时对象模型服务
CObject
和 CRuntimeClass
类封装几个对象服务,包括访问运行时类信息、序列化和动态对象创建。 所有派生自 CObject
的类都继承此功能。
能够访问运行时类信息可让您在运行时确定有关对象的类的信息。 当需要对函数参数进行额外的类型检查以及必须基于对象的类编写专用代码时很有用,能够在运行时确定对象的类很有用。 C++ 语言不直接支持运行时类信息。
序列化是在文件中写入或读取对象内容的过程。 当应用程序退出后,可以使用序列化来存储对象的内容。 对象随后可在应用程序重新启动时从文件中读取。 此类数据对象被称为“永久对象”。
动态对象创建支持在运行时创建指定类的对象。 例如,文档、视图和框架对象必须支持动态创建,因为框架需要以动态方式创建这些内容。
下表列出了支持运行时类信息、序列化和动态创建的 MFC 宏。
有关这些运行时对象服务和序列化的详细信息,请参阅 CObject
类:访问运行时类信息一文。
运行时对象模型服务宏
名称 | 描述 |
---|---|
DECLARE_DYNAMIC |
支持访问运行时类信息(必须在类声明中使用)。 |
DECLARE_DYNCREATE |
支持动态创建和访问运行时类信息(必须在类声明中使用)。 |
DECLARE_SERIAL |
支持序列化和访问运行时类信息(必须在类声明中使用)。 |
IMPLEMENT_DYNAMIC |
支持访问运行时类信息(必须在类实现中使用)。 |
IMPLEMENT_DYNCREATE |
支持动态创建和访问运行时类信息(必须在类实现中使用)。 |
IMPLEMENT_SERIAL |
允许序列化和访问运行时类信息(必须在类实现中使用)。 |
RUNTIME_CLASS |
返回与命名类对应的 CRuntimeClass 结构。 |
OLE 通常要求在运行时动态创建对象。 例如,OLE 服务器应用程序必须能够动态创建 OLE 项以响应来自客户端的请求。 同样,自动化服务器必须能够创建项以响应来自自动化客户端的请求。
Microsoft 基础类库提供了两个特定于 OLE 的宏。
OLE 对象的动态创建
名称 | 描述 |
---|---|
AFX_COMCTL32_IF_EXISTS |
确定公共控件库是否实现了指定的 API。 |
AFX_COMCTL32_IF_EXISTS2 |
确定公共控件库是否实现了指定的 API。 |
DECLARE_OLECREATE |
支持通过 OLE 自动化创建对象。 |
DECLARE_OLECTLTYPE |
声明控件类的 GetUserTypeNameID 和 GetMiscStatus 成员函数。 |
DECLARE_PROPPAGEIDS |
声明 OLE 控件提供一个属性页列表来显示其属性。 |
IMPLEMENT_OLECREATE |
支持由 OLE 系统创建对象。 |
IMPLEMENT_OLECTLTYPE |
实现控件类的 GetUserTypeNameID 和 GetMiscStatus 成员函数。 |
IMPLEMENT_OLECREATE_FLAGS |
此宏或 IMPLEMENT_OLECREATE 必须出现在任何使用 DECLARE_OLECREATE 的类的实现文件中。 |
AFX_COMCTL32_IF_EXISTS
确定公共控件库是否实现了指定的 API。
语法
AFX_COMCTL32_IF_EXISTS( proc );
参数
proc
指向包含函数名的以 null 结尾的字符串的指针,或者指定函数的序号值。 如果此参数是序号值,则它必须在低序位字中;高序位字必须为零。 此参数必须采用 Unicode。
备注
使用此宏可确定公共控件库是否包含通过 proc
(而不是通过调用 GetProcAddress
)指定的函数。
要求
%>
AFX_COMCTL32_IF_EXISTS2
确定公共控件库是否实现了指定的 API(这是 AFX_COMCTL32_IF_EXISTS
的 Unicode 版本)。
语法
AFX_COMCTL32_IF_EXISTS2( proc );
参数
proc
指向包含函数名的以 null 结尾的字符串的指针,或者指定函数的序号值。 如果此参数是序号值,则它必须在低序位字中;高序位字必须为零。 此参数必须采用 Unicode。
备注
使用此宏可确定公共控件库是否包含通过 proc
(而不是通过调用 GetProcAddress
)指定的函数。 此宏是 AFX_COMCTL32_IF_EXISTS
的 Unicode 版本。
要求
%>
DECLARE_DYNAMIC
添加从 CObject
派生类时访问有关对象的类的运行时信息的功能。
DECLARE_DYNAMIC(class_name)
参数
class_name
类的实际名称。
备注
将 DECLARE_DYNAMIC
宏添加到类的标头 (.h
) 模块,然后将该模块包含在需要访问此类的对象的所有 .cpp
模块中。
如果按照描述使用 DECLARE_DYNAMIC
和 IMPLEMENT_DYNAMIC
宏,就可以使用 RUNTIME_CLASS
宏和 CObject::IsKindOf
函数来确定运行时对象的类。
如果 DECLARE_DYNAMIC
包含在类声明中,则 IMPLEMENT_DYNAMIC
必须包含在类实现中。
有关 DECLARE_DYNAMIC
宏的详细信息,请参阅 CObject
类主题。
示例
请参阅 IMPLEMENT_DYNAMIC
的示例。
要求
标头:afx.h
DECLARE_DYNCREATE
支持在运行时动态创建 CObject
派生的类的对象。
DECLARE_DYNCREATE(class_name)
参数
class_name
类的实际名称。
备注
该框架使用此功能来动态地新建对象。 例如打开新文档时创建的新视图。 文档、视图和框架类应支持动态创建,因为框架需要以动态方式创建这些类。
将 DECLARE_DYNCREATE
宏添加到类的 .h
模块,然后将该模块包含在需要访问此类的对象的所有 .cpp
模块中。
如果 DECLARE_DYNCREATE
包含在类声明中,则 IMPLEMENT_DYNCREATE
必须包含在类实现中。
有关 DECLARE_DYNCREATE
宏的详细信息,请参阅 CObject
类主题。
注意
DECLARE_DYNCREATE
宏包括 DECLARE_DYNAMIC
的所有功能。
示例
请参阅 IMPLEMENT_DYNCREATE
的示例。
要求
标头:afx.h
DECLARE_OLECTLTYPE
声明控件类的 GetUserTypeNameID
和 GetMiscStatus
成员函数。
语法
DECLARE_OLECTLTYPE( class_name )
参数
class_name
控件类的名称。
注解
GetUserTypeNameID
和 GetMiscStatus
为纯虚函数,是在 COleControl
中声明的。 这些函数是纯虚函数,因此必须在控件类中重写它们。 除 DECLARE_OLECTLTYPE
外,还需要将 IMPLEMENT_OLECTLTYPE
宏添加到控件类声明中。
要求
标头:afxctl.h
DECLARE_PROPPAGEIDS
声明 OLE 控件提供一个属性页列表来显示其属性。
语法
DECLARE_PROPPAGEIDS( class_name )
参数
class_name
拥有属性页面的控件类的名称。
备注
在类声明末尾使用 DECLARE_PROPPAGEIDS
宏。 然后,在定义类的成员函数的 .cpp
文件中,使用 BEGIN_PROPPAGEIDS
宏、控件的每个属性页的宏条目和 END_PROPPAGEIDS
宏来声明属性页列表的结尾。
有关属性页的详细信息,请参阅 ActiveX 控件:属性页一文。
要求
标头:afxctl.h
DECLARE_SERIAL
生成可序列化的 CObject
派生类所必需的 C++ 标头代码。
DECLARE_SERIAL(class_name)
参数
class_name
类的实际名称。
注解
序列化是向文件写入或从文件读取对象内容的过程。
在 .h
模块中使用 DECLARE_SERIAL
宏,然后将该模块包含在需要访问此类的对象的所有 .cpp
模块中。
如果 DECLARE_SERIAL
包含在类声明中,则 IMPLEMENT_SERIAL
必须包含在类实现中。
DECLARE_SERIAL
宏包括 DECLARE_DYNAMIC
和 DECLARE_DYNCREATE
的所有功能。
你可以使用 AFX_API
宏,为使用 DECLARE_SERIAL
和 IMPLEMENT_SERIAL
宏的类自动导出 CArchive
提取运算符。 使用以下代码将类声明(位于 .h
文件中)括起来:
#undef AFX_API
#define AFX_API AFX_EXT_CLASS
// <your class declarations here>
#undef AFX_API
#define AFX_API
有关 DECLARE_SERIAL
宏的详细信息,请参阅 CObject
类主题。
示例
class CAge : public CObject
{
public:
void Serialize(CArchive& ar);
DECLARE_SERIAL(CAge)
// remainder of class declaration omitted
要求
标头:afx.h
IMPLEMENT_DYNAMIC
生成动态 CObject
派生类所需的 C++ 代码,该类对层次结构中的类名和位置具有运行时访问权限。
IMPLEMENT_DYNAMIC(class_name, base_class_name)
参数
class_name
类的实际名称。
base_class_name
基类的名称。
备注
在 .cpp
模块中使用 IMPLEMENT_DYNAMIC
宏,然后仅链接一次所得的对象代码。
有关详细信息,请参阅 CObject
类主题。
示例
class CPerson : public CObject
{
DECLARE_DYNAMIC(CPerson)
// other declarations
};
IMPLEMENT_DYNAMIC(CPerson, CObject)
要求
标头:afx.h
IMPLEMENT_DYNCREATE
与 DECLARE_DYNCREATE
宏一起使用时,支持在运行时动态地创建 CObject
派生类的对象。
IMPLEMENT_DYNCREATE(class_name, base_class_name)
参数
class_name
类的实际名称。
base_class_name
基类的实际名称。
备注
框架使用此功能动态地创建新对象(例如在序列化期间从磁盘读取对象时)。 在类实现文件中添加 IMPLEMENT_DYNCREATE
宏。 有关详细信息,请参阅 CObject
类主题。
如果使用 DECLARE_DYNCREATE
和 IMPLEMENT_DYNCREATE
宏,就可以使用 RUNTIME_CLASS
宏和 CObject::IsKindOf
成员函数来确定运行时对象的类。
如果 DECLARE_DYNCREATE
包含在类声明中,则 IMPLEMENT_DYNCREATE
必须包含在类实现中。
请注意,此宏定义将调用类的默认构造函数。 如果类显式实现非普通构造函数,则还必须显式实现默认构造函数。 可以将默认构造函数添加到类的 private
或 protected
成员部分,以防止从类实现外部调用该构造函数。
示例
class CMyDynCreateObj : public CObject
{
int m_Num;
public:
DECLARE_DYNCREATE(CMyDynCreateObj)
CMyDynCreateObj(int Num) { m_Num = Num; }
private:
CMyDynCreateObj() { m_Num = 0; } // provide default constructor only for
// dynamic creation
};
IMPLEMENT_DYNCREATE(CMyDynCreateObj, CObject)
要求
标头:afx.h
IMPLEMENT_OLECREATE_FLAGS
此宏或 IMPLEMENT_OLECREATE
必须出现在任何使用 DECLARE_OLECREATE
的类的实现文件中。
语法
IMPLEMENT_OLECREATE_FLAGS( class_name, external_name, nFlags,
l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
参数
class_name
类的实际名称。
external_name
向其他应用程序公开的对象名(用引号引起来)。
nFlags
包含下列一个或多个标志:
afxRegInsertable
允许控件显示在 OLE 对象的“插入对象”对话框中。afxRegApartmentThreading
将注册表中的线程模型设置为ThreadingModel=Apartment
。afxRegFreeThreading
将注册表中的线程模型设置为ThreadingModel=Free
。
可以将 afxRegApartmentThreading
和 afxRegFreeThreading
这两个标志合并起来,以设置 ThreadingModel=Both。 请参阅 Windows SDK 中的 InprocServer32
,了解有关线程模型注册的详细信息。
l
、w1
、w2
、b1
、b2
、b3
、b4
、b5
、b6
、b7
、b8
类的 CLSID 的组件。
备注
注意
如果使用 IMPLEMENT_OLECREATE_FLAGS
,可使用 nFlags
参数来指定对象支持的线程模型。 如果只想支持单线程模型,请使用 IMPLEMENT_OLECREATE
。
外部名称是向其他应用程序公开的标识符。 客户端应用程序使用外部名称从自动化服务器请求此类的对象。
OLE 类 ID 是对象的 128 位的唯一标识符。 它包含一个 long
,两个 **WORD
**,三个 **BYTE
**,它们分别由 l
、w1
、w2
以及语法描述中的 b1
到 b8
表示。 应用程序向导和代码向导根据需要为你创建唯一的 OLE 类 ID。
要求
标头:afxdisp.h
IMPLEMENT_OLECTLTYPE
实现控件类的 GetUserTypeNameID
和 GetMiscStatus
成员函数。
语法
DECLARE_OLECTLTYPE( class_name, idsUserTypeName, dwOleMisc )
参数
class_name
控件类的名称。
idsUserTypeName
包含控件外部名称的字符串的资源 ID。
dwOleMisc
包含一个或多个标志的枚举。 有关此枚举的详细信息,请参阅 Windows SDK 中的 OLEMISC
。
备注
除 IMPLEMENT_OLECTLTYPE
外,还需要将 DECLARE_OLECTLTYPE
宏添加到控件类声明中。
GetUserTypeNameID
成员函数返回标识控件类的资源字符串。 GetMiscStatus
返回控件的 OLEMISC
位。 此枚举指定描述控件的各种特性的一系列设置。 有关 OLEMISC
设置的完整说明,请参阅 Windows SDK 中的 OLEMISC
。
注意
ActiveX ControlWizard 使用的默认设置为:OLEMISC_ACTIVATEWHENVISIBLE
、OLEMISC_SETCLIENTSITEFIRST
、OLEMISC_INSIDEOUT
、OLEMISC_CANTLINKINSIDE
和 OLEMISC_RECOMPOSEONRESIZE
。
要求
标头:afxctl.h
IMPLEMENT_SERIAL
生成动态 CObject
派生类所需的 C++ 代码,该类对层次结构中的类名和位置具有运行时访问权限。
IMPLEMENT_SERIAL(class_name, base_class_name, wSchema)
参数
class_name
类的实际名称。
base_class_name
基类的名称。
wSchema
将在存档中编码的 UINT 版本号,用于使反序列化程序能够识别和处理早期程序版本创建的数据。 类的架构编号不得为 -1。
注解
在 .cpp
模块中使用 IMPLEMENT_SERIAL
宏,然后仅链接一次所得的对象代码。
你可以使用 AFX_API
宏,为使用 DECLARE_SERIAL
和 IMPLEMENT_SERIAL
宏的类自动导出 CArchive
提取运算符。 使用以下代码将类声明(位于 .h
文件中)括起来:
#undef AFX_API
#define AFX_API AFX_EXT_CLASS
// <your class declarations here>
#undef AFX_API
#define AFX_API
有关详细信息,请参阅 CObject
类主题。
示例
IMPLEMENT_SERIAL(CAge, CObject, VERSIONABLE_SCHEMA | 2)
要求
标头:afx.h
RUNTIME_CLASS
从 C++ 类的名称获取运行时类结构。
RUNTIME_CLASS(class_name)
参数
class_name
类的实际名称(未用引号括起)。
备注
RUNTIME_CLASS
返回 class_name
指定的类的 CRuntimeClass
结构的指针。 仅使用 DECLARE_DYNAMIC
、DECLARE_DYNCREATE
或 DECLARE_SERIAL
声明的 CObject
派生类将返回 CRuntimeClass
结构的指针。
有关详细信息,请参阅 CObject
类主题。
示例
CRuntimeClass* prt = RUNTIME_CLASS(CAge);
ASSERT(strcmp(prt->m_lpszClassName, "CAge") == 0);
要求
标头:afx.h
DECLARE_OLECREATE
支持通过 OLE 自动化创建 CCmdTarget
派生类的对象。
DECLARE_OLECREATE(class_name)
参数
class_name
类的实际名称。
备注
此宏使其他支持 OLE 的应用程序能够创建此类型的对象。
将 DECLARE_OLECREATE
宏添加到类的 .h
模块,然后将该模块包含在需要访问此类的对象的所有 .cpp
模块中。
如果 DECLARE_OLECREATE
包含在类声明中,则 IMPLEMENT_OLECREATE
必须包含在类实现中。 使用 DECLARE_OLECREATE
的类声明也必须使用 DECLARE_DYNCREATE
或 DECLARE_SERIAL
。
要求
标头:afxdisp.h
IMPLEMENT_OLECREATE
此宏或 IMPLEMENT_OLECREATE_FLAGS
必须出现在任何使用 DECLARE_OLECREATE
的类的实现文件中。
IMPLEMENT_OLECREATE(class_name, external_name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
参数
class_name
类的实际名称。
external_name
向其他应用程序公开的对象名(用引号引起来)。
l
、w1
、w2
、b1
、b2
、b3
、b4
、b5
、b6
、b7
、b8
类的 CLSID 的组件。
备注
注意
如果你使用 IMPLEMENT_OLECREATE
,则默认只支持单线程模型。 如果使用 IMPLEMENT_OLECREATE_FLAGS
,可使用 nFlags
参数来指定对象支持的线程模型。
外部名称是向其他应用程序公开的标识符。 客户端应用程序使用外部名称从自动化服务器请求此类的对象。
OLE 类 ID 是对象的 128 位的唯一标识符。 它包含一个 long
,两个 **WORD
**,三个 **BYTE
**,它们分别由 l
、w1
、w2
以及语法描述中的 b1
到 b8
表示。 应用程序向导和代码向导根据需要为你创建唯一的 OLE 类 ID。
要求
标头:afxdisp.h