运行时对象模型服务

CObjectCRuntimeClass 类封装几个对象服务,包括访问运行时类信息、序列化和动态对象创建。 所有派生自 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 声明控件类的 GetUserTypeNameIDGetMiscStatus 成员函数。
DECLARE_PROPPAGEIDS 声明 OLE 控件提供一个属性页列表来显示其属性。
IMPLEMENT_OLECREATE 支持由 OLE 系统创建对象。
IMPLEMENT_OLECTLTYPE 实现控件类的 GetUserTypeNameIDGetMiscStatus 成员函数。
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_DYNAMICIMPLEMENT_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

声明控件类的 GetUserTypeNameIDGetMiscStatus 成员函数。

语法

DECLARE_OLECTLTYPE( class_name )

参数

class_name
控件类的名称。

注解

GetUserTypeNameIDGetMiscStatus 为纯虚函数,是在 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_DYNAMICDECLARE_DYNCREATE 的所有功能。

你可以使用 AFX_API 宏,为使用 DECLARE_SERIALIMPLEMENT_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_DYNCREATEIMPLEMENT_DYNCREATE 宏,就可以使用 RUNTIME_CLASS 宏和 CObject::IsKindOf 成员函数来确定运行时对象的类。

如果 DECLARE_DYNCREATE 包含在类声明中,则 IMPLEMENT_DYNCREATE 必须包含在类实现中。

请注意,此宏定义将调用类的默认构造函数。 如果类显式实现非普通构造函数,则还必须显式实现默认构造函数。 可以将默认构造函数添加到类的 privateprotected 成员部分,以防止从类实现外部调用该构造函数。

示例

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

可以将 afxRegApartmentThreadingafxRegFreeThreading 这两个标志合并起来,以设置 ThreadingModel=Both。 请参阅 Windows SDK 中的 InprocServer32,了解有关线程模型注册的详细信息。

lw1w2b1b2b3b4b5b6b7b8 类的 CLSID 的组件。

备注

注意

如果使用 IMPLEMENT_OLECREATE_FLAGS,可使用 nFlags 参数来指定对象支持的线程模型。 如果只想支持单线程模型,请使用 IMPLEMENT_OLECREATE

外部名称是向其他应用程序公开的标识符。 客户端应用程序使用外部名称从自动化服务器请求此类的对象。

OLE 类 ID 是对象的 128 位的唯一标识符。 它包含一个 long,两个 **WORD**,三个 **BYTE**,它们分别由 lw1w2 以及语法描述中的 b1b8 表示。 应用程序向导和代码向导根据需要为你创建唯一的 OLE 类 ID。

要求

标头afxdisp.h

IMPLEMENT_OLECTLTYPE

实现控件类的 GetUserTypeNameIDGetMiscStatus 成员函数。

语法

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_ACTIVATEWHENVISIBLEOLEMISC_SETCLIENTSITEFIRSTOLEMISC_INSIDEOUTOLEMISC_CANTLINKINSIDEOLEMISC_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_SERIALIMPLEMENT_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_DYNAMICDECLARE_DYNCREATEDECLARE_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_DYNCREATEDECLARE_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
向其他应用程序公开的对象名(用引号引起来)。

lw1w2b1b2b3b4b5b6b7b8 类的 CLSID 的组件。

备注

注意

如果你使用 IMPLEMENT_OLECREATE,则默认只支持单线程模型。 如果使用 IMPLEMENT_OLECREATE_FLAGS,可使用 nFlags 参数来指定对象支持的线程模型。

外部名称是向其他应用程序公开的标识符。 客户端应用程序使用外部名称从自动化服务器请求此类的对象。

OLE 类 ID 是对象的 128 位的唯一标识符。 它包含一个 long,两个 **WORD**,三个 **BYTE**,它们分别由 lw1w2 以及语法描述中的 b1b8 表示。 应用程序向导和代码向导根据需要为你创建唯一的 OLE 类 ID。

要求

标头afxdisp.h

另请参阅

宏和全局函数
隔离 MFC 公用控件库
CLSID 项