ATL 复制策略类
复制策略类是用于初始化、复制和删除数据的实用工具类。 使用复制策略类,你可以为任何类型的数据定义复制语义,并定义不同数据类型之间的转换。
ATL 在以下模板的实现中使用复制策略类:
通过将复制或转换数据所需的信息封装在可作为模板参数传递的复制策略类中,ATL 开发人员为这些类的极致可重用性做好了准备。 例如,如果需要使用任意数据类型来实现某个集合,则只需提供适当的复制策略;不需接触实现集合的代码。
定义
根据定义,提供以下静态函数的类是复制策略类:
static void init(
DestinationType
* p);
static HRESULT copy(
DestinationType
* pTo, const
SourceType
* pFrom);
static void destroy(
DestinationType
* p);
可以将类型 DestinationType
和 SourceType 替换为每个复制策略的任意数据类型。
注意
尽管可以为任意数据类型定义复制策略类,但 在 ATL 代码中使用类时,应仅限那些有意义的类型。 例如,将复制策略类用于 ATL 的集合或枚举器实现时,DestinationType
必须是一种可用作 COM 接口方法中的参数的类型。
使用 init 初始化数据、使用 copy 复制数据,使用 destroy 释放数据。 初始化、复制和销毁的精确含义是复制策略类的域,具体取决于所涉及的数据类型。
有两个针对复制策略类的使用和实现的要求:
要 copy 的第一个参数只能接收一个指向以前已使用 init 进行初始化的数据的指针。
destroy 只能收到一个指向以前已使用 init 进行初始化或通过 copy 进行复制的数据的指针。
标准实现
ATL 以 _Copy
和 _CopyInterface
模板类的形式提供两个复制策略类:
_Copy
类仅允许同类复制(不转换数据类型),因为它仅提供一个模板参数来指定DestinationType
和 SourceType。 此模板的泛型实现不包含初始化或销毁代码,使用memcpy
来复制数据。 ATL 还为 VARIANT、LPOLESTR、OLEVERB 和 CONNECTDATA 数据类型提供_Copy
专用化。_CopyInterface
类提供一个实现,用于复制遵循标准 COM 规则的接口指针。 同样,此类只允许同类复制,因此它使用简单的赋值和对AddRef
的调用来执行复制。
自定义实现
通常,需要为异类复制(即转换数据类型)定义你自己的复制策略类。 有关自定义复制策略类的一些示例,请查看 ATLCollections 示例中的 VCUE_Copy.h 和 VCUE_CopyString.h 文件。 这些文件包含两个模板复制策略类(GenericCopy
和 MapCopy
)以及多个适用于不同数据类型的 GenericCopy
专用化。
GenericCopy
使用 GenericCopy
,你可以指定 SourceType 和 DestinationType
作为模板参数。 下面是 VCUE_Copy.h 中的 GenericCopy
类的最常规形式:
template <class DestinationType, class SourceType = DestinationType>
class GenericCopy
{
public :
typedef DestinationType destination_type;
typedef SourceType source_type;
static void init(destination_type* p)
{
_Copy<destination_type>::init(p);
}
static void destroy(destination_type* p)
{
_Copy<destination_type>::destroy(p);
}
static HRESULT copy(destination_type* pTo, const source_type* pFrom)
{
return _Copy<destination_type>::copy(pTo, const_cast<source_type*>(pFrom));
}
}; // class GenericCopy
VCUE_Copy.h 还包含此类的下述专用化:GenericCopy<BSTR>
、GenericCopy<VARIANT, BSTR>
、GenericCopy<BSTR, VARIANT>
。 VCUE_CopyString.h 包含从 std::string 进行的复制的专用化:GenericCopy<std::string>
、GenericCopy<VARIANT, std::string>
和 GenericCopy<BSTR, std::string>
。 可以通过提供你自己的进一步专用化来增强 GenericCopy
。
MapCopy
MapCopy
假定要复制的数据存储在 C++ 标准库样式映射中,因此,它允许你指定存储数据的映射的类型和目标类型。 类的实现只是使用 MapType 类提供的 typedefs 来确定源数据类型并调用相应的 GenericCopy
类。 不需要此类的专用化。
template <class MapType, class DestinationType = MapType::mapped_type>
class MapCopy
{
public :
typedef DestinationType destination_type;
typedef typename MapType::value_type source_type;
typedef MapType map_type;
typedef typename MapType::mapped_type pseudosource_type;
static void init(destination_type* p)
{
GenericCopy<destination_type, pseudosource_type>::init(p);
}
static void destroy(destination_type* p)
{
GenericCopy<destination_type, pseudosource_type>::destroy(p);
}
static HRESULT copy(destination_type* pTo, const source_type* pFrom)
{
return GenericCopy<destination_type, pseudosource_type>::copy(pTo, &(pFrom->second));
}
}; // class MapCopy