このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
HardLinkIconID のインスタンスの作成ができないのは、
HardLinkIconID の定義が完全でないため、
具象クラスになることができないのが理由である。
では、何が不足しているのか。
HardLinkIconID は、IShellIconOverlayIdentifier と、
Object の 2 つを継承した、多重継承クラスである。
IShellIconOverlayIdentifier は IUnknown を、
Object も IUnknown を継承しているので、
HardLinkIconID の逆継承木を書くと以下のようになる。
HardLinkIconID
+ Object
+ IUnknown
+ IShellIconOverlayIdentifier
+ IUnknown
IUnknown の実体が 2 つ含まれることに注意。
C++ にはインタフェースがないので、
継承した全てのクラスの抽象メンバを実装する必要がある。
HardLinkIconID が実体化できない理由は、
IShellIconOverlayIdentifier 側の IUnknown の、
AddRef と Release を実装(オーバライド)していないため、
HardLinkIconID が抽象クラスとなってしまったからだ。
Object は IUnknown のメソッドを実装しているが、
これは、IShellIconOverlayIdentifier 側の
IUnknown には全く関係ないことなのである。
これに対する対策は、HardLinkIconID で、
AddRef と Release をオーバライドすることである。
では、HardLinkIconID を変更してみよう。
========== HardLinkIconID.hpp ==========
//(…前略…)
class HardLinkIconID :
public Object,
public IShellIconOverlayIdentifier {
// インタフェース
public:
// IUnknown の実装
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [out] */ void** ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
//(…後略…)
========== end of HardLinkIconID.hpp ==========
こうすることで、両方の IUnknown のメソッドを、
実装したことになる。
========== HardLinkIconID.cpp ==========
//(…前略…)
//(…HardLinkIconID::QueryInterface…)
ULONG STDMETHODCALLTYPE HardLinkIconID::AddRef() {
return Object::AddRef();
}
ULONG STDMETHODCALLTYPE HardLinkIconID::Release() {
return Object::Release();
}
//(…後略…)
========== end of HardLinkIconID.cpp ==========
AddRef と Release の基本実装は、
Object クラスに存在するため、
HardLinkIconID の AddRef と Release は、
Object クラスの同メソッドに委譲する必要がある。
C++ では多重継承が可能なので、
基底クラスは 1 つだけとは限らない。
そのため、C# の base や Java の super のようには書けず、
スコープ解決演算子(::)を用いて、
「基底クラス::メソッド」として呼び出すのだ。
これで、コンパイルが通るようになったはずだ。