2006 年 11 月 26 日 22 時 28 分

多重継承の問題点


このアーカイブは同期化されません。 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 のようには書けず、
スコープ解決演算子(::)を用いて、
「基底クラス::メソッド」として呼び出すのだ。

これで、コンパイルが通るようになったはずだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.