このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
テンプレートクラスは、定義しただけでは何の効果もない。
テンプレートの引数に具体的なクラス型を与えることで、
テンプレートを元にしたクラスの実体が定義される。
これを、「テンプレートのインスタンス化」と呼ぶ。
では、DllGetClassObject を書き換えて、
他の 2 クラスも公開できるように修正する。
どうせなら、HardLinkIconID にもテンプレートを使おう。
=========== library.cpp ==========
#include "global.hpp"
#include "HardLinkIconID.hpp"
#include "MountPointIconID.hpp"
#include "FolderLinkIconID.hpp"
#include "ClassObject.hpp"
// (…DllMain…)
STDAPI DllGetClassObject(
/* [in] */ REFCLSID rclsid,
/* [in] */ REFIID riid,
/* [out] */ void** ppvObject) {
// クラスオブジェクトの唯一のインスタンス
static ClassObject<HardLinkIconID> hardLinkClass;
static ClassObject<MountPointIconID> mountPointClass;
static ClassObject<FolderLinkIconID> folderLinkClass;
// ppvObject が NULL なら例外
if (ppvObject == NULL) return E_INVALIDARG;
// ppvObject は out なので、
// ポインタが指す元の値は無視できる
*ppvObject = NULL;
IUnknown* classObject = NULL;
// 対応するクラスオブジェクトを取得
if (IsEqualCLSID(rclsid, CLSID_HardLinkIconID)) {
classObject = &hardLinkClass;
} else if (IsEqualCLSID(rclsid, CLSID_MountPointIconID)) {
classObject = &mountPointClass;
} else if (IsEqualCLSID(rclsid, CLSID_FolderLinkIconID)) {
classObject = &folderLinkClass;
} else {
return CLASS_E_CLASSNOTAVAILABLE;
}
// クラスオブジェクトへの参照を追加
classObject->AddRef();
// インタフェースを要求
HRESULT result = classObject->QueryInterface(riid, ppvObject);
// 参照を解放
classObject->Release();
return result;
}
=========== end of library.cpp ==========
ClassObject<HardLinkIconID> という記述によって、
HardLinkIconID を実引数として
ClassObject テンプレートがインスタンス化され、
ClassObject<HardLinkIconID> というクラスが定義される。
これは通常の型と同じように扱われるので、
型が必要な箇所で自由に使うことができる。
C++ のテンプレートは柔軟であり、
テンプレートを基にした型が 1 度でも使われると、
自動的にインスタンス化してくれる。
そのため、実体がどこで定義されるかは考える必要はない。
あとは、新たに追加で作成した 2 クラスに対応した、
クラス ID を作成し、global.[ch]pp に追加しよう。
========== global.hpp ==========
#ifndef global_hpp_included
#define global_hpp_included
#define STRICT
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
// グローバル変数
extern HMODULE g_moduleHandle;
extern volatile long g_serverLockCount;
// グローバル定数
extern const GUID CLSID_HardLinkIconID;
extern const GUID CLSID_MountPointIconID;
extern const GUID CLSID_FolderLinkIconID;
#endif // !global_hpp_included
========== end of global.hpp ==========
========== global.cpp ==========
#include "global.hpp"
// グローバル変数の定義(実体)
extern HMODULE g_moduleHandle = NULL;
extern volatile long g_serverLockCount = 0;
// グローバル定数の定義(実体)
// {755525B6-51FB-490b-A21B-91F7208C9429}
extern const GUID CLSID_HardLinkIconID = {
0x755525b6, 0x51fb, 0x490b,
{ 0xa2, 0x1b, 0x91, 0xf7, 0x20, 0x8c, 0x94, 0x29 }
};
// {88A49CB3-675A-4093-9C7C-66336E30A760}
extern const GUID CLSID_MountPointIconID = {
0x88a49cb3, 0x675a, 0x4093,
{ 0x9c, 0x7c, 0x66, 0x33, 0x6e, 0x30, 0xa7, 0x60 }
};
// {7B0F3F52-0D6E-4570-A397-E69EC97D241B}
extern const GUID CLSID_FolderLinkIconID = {
0x7b0f3f52, 0xd6e, 0x4570,
{ 0xa3, 0x97, 0xe6, 0x9e, 0xc9, 0x7d, 0x24, 0x1b }
};
========== end of global.cpp ==========
これで、DllGetClassObject の実装は完了となる。