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 類別所提供的 typedef 來確定來源資料的類型並呼叫適當的 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