【问题标题】:COM - avoid implementing IUnknown repeatedlyCOM - 避免重复执行 IUnknown
【发布时间】:2015-02-08 23:23:43
【问题描述】:

我正在尝试为 Internet Explorer 实现一个基本的浏览器帮助对象。我有 2 个类,一个必须实现 IClassFactory,一个必须实现 IObjectWithSite。这两个接口都继承自 IUnknown。为了避免重复实现 IUnknown,我创建了一个基类 Unknown,这样对于给定的子类,我只需要实现它的直接父接口。这是我的班级声明:

class Child1 : public Unknown<IObjectWithSite>

class Child2 : public Unknown<IClassFactory>

template <class T>
class Unknown : public T

我这样做是为了避免钻石问题。

Child1 ---> Unknown ---> IObjectWithSite

Child2 ---> Unknown ---> IClassFactory

在 Unknown 中,我实现了从 T 继承的 IUnknown 方法。

我似乎无法让它工作。我在这里错过了什么吗?我是不是走错路了?

编辑:这是下面的代码

未知.h

#pragma once

#include <OCIdl.h>
#include <Unknwn.h>

template <class T>
class Unknown : public T
{

protected:

    // Reference count to this COM class
    ULONG m_comRef;

public:

    // IUnknown methods
    STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
    {
        // Implementation...
    }

    STDMETHODIMP_(ULONG) AddRef()
    {
        // Implementation...
    }

    STDMETHODIMP_(ULONG) Release()
    {
        // Implementation...
    }

};

Child1.h

#pragma once

#include "Unknown.h"

template <class T>
class Child1 : public Unknown<T>
{

public:

    STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);

};

STDMETHODIMP Child1<IClassFactory>::QueryInterface(REFIID riid, void** ppvObject) {
    // implementation...
}

etc...

孩子2:

#pragma once

#include "Unknown.h"

template <class T>
class Child2 : public Unknown<T>
{

public:

    STDMETHODIMP SetSite(IUnknown*);

    STDMETHODIMP GetSite(REFIID, void**);

    STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);

};

STDMETHODIMP Child2<IObjectWithSite>::SetSite(IUnknown*) {
     // Implementation...
}

etc...

【问题讨论】:

  • “我似乎无法让它工作”是什么意思?它不编译?它不运行?您看到了什么错误?
  • 很多。我得到的第一个构建错误是指向 Child2 的定义,说“使用类模板需要模板参数列表”。
  • 您应该发布您的原始代码,即您发布问题时所拥有的代码,并说明哪一行给出了错误。另请注意,这并不能真正解决任何问题,它只是避免您一遍又一遍地实现IUnknown 的方法。但是,您似乎想在子类中覆盖QueryInterface,因此它只会避免您重新实现AddRefRelease

标签: c++ windows internet-explorer inheritance com


【解决方案1】:

您应该将您的子类声明更改为:

template <class T>
class Child1 : public Unknown<T>

你在类声明中实例化父模板,这是不允许的。

在函数实现中,还是需要用到T:

template <class T>
STDMETHODIMP Child2<T>::SetSite(IUnknown*) {
     // Implementation...
}

对于你的问题,你不需要声明2个子类,你可以简单的使用:

Unknown<IObjectWithSite> child1;
Unknown<IClassFactory> child2;

在实例化模板时,编译器会创建一个新类型,因此Unknown&lt;IObjectWithSite&gt;Unknown&lt;IClassFactory&gt; 是实现了 IUnknown 的不同类型。

【讨论】:

  • 对。在我的实现中,我指定了实际的类型参数?像 Child1::myMethod。默认构造函数会在这里工作吗?
  • 好的,我试过了,但没有运气。我在头文件中有 Unknown 的声明,我将其包含在 Child1 和 Child2 的声明的头文件中。由于这 3 个类是模板,因此实现也包含在头文件中。我仍然收到“未知:使用类模板需要模板参数列表”,即使 Child1(和 Child2)声明如下: template class Child1 : public Unknown
  • 我已经用现在包含的代码编辑了问题。
  • 我有 2 个子类,因为我需要实现除 IUnknown 之外的其他接口。为什么我不需要它们?另外,当我实现该方法时,我肯定需要传递类型参数的实际参数吗?
  • Child1Child2 不必是模板。恩,请考虑发布您的原始代码,而不是模板版本。
【解决方案2】:

是的,你做错了。使用 ATL。花时间编写功能,而不是重新实现 IUnknown 和 IClassFactory。

【讨论】:

  • 我对 COM 完全陌生,之前也没有使用过 ATL。所以我想从一个简单的方法开始,以更好地理解 COM。
  • 链接,例如现有的IUnknown implementations 和示例会使答案更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多