【问题标题】:Avoiding explicit constructor calls of virtual base classes避免虚拟基类的显式构造函数调用
【发布时间】:2014-09-09 15:18:24
【问题描述】:

基本问题:是否可以避免显式调用每个虚拟基类的(非默认)构造函数?

背景:我正在研究一些围绕 Windows COM 对象的类型安全的 C++ 包装类。我目前的方法是有一个CBaseCOMWrapper 类,它封装了一个IUnknown 对象以进行引用计数。然后,我有一个从CBaseCOMWrapper 继承的CCOMWrapper 模板类,它为特定的COM 类型(即IDXGIObjectID3D11Device 等)定义了一个包装器。最后,独立的类从这些包装模板继承以提供实际/额外的功能(即CDXGIObjectCD3D11Device)。

例如,我有以下类(成员省略):

class CBaseCOMWrapper { };

template<typename T> // here, T should inherit from IUnknown
class CCOMWrapper : public virtual CBaseCOMWrapper { };

class CDXGIObject : public virtual CCOMWrapper<IDXGIObject> { };

template<>
class CCOMWrapper<IDXGIAdapter> : public virtual CCOMWrapper<IDXGIObject> { };

class CDXGIAdapter : public virtual CCOMWrapper<IDXGIAdapter> { };

这是类型层次结构的对应图:

左列是实际对象,中列是精简的 COM 包装器,右列是实际的 COM 对象。实线箭头表示继承,虚线箭头表示封装。

我使用CCOMWrapper 的模板特化来提供中间的父子关系。

问题:包装类假定一个指向 COM 对象的非 NULL(又名有效)指针,所以我不能有默认构造函数。因为层次结构充满了“钻石”,所以大部分继承是虚拟的;这意味着每个类的构造函数都必须调用构造函数。所以,在上面的例子中,CDXGIAdapter的构造函数必须调用CCOMWrapper&lt;IDXGIAdapter&gt;CDXGIObjectCCOMWrapper&lt;IDXGIObject&gt;CBaseCOMWrapper的构造函数。随着层次结构的扩展(即ID3D11Predicate 的继承链有 4 个“链接”长),这意味着必须调用更多的构造函数。

可能的解决方案:理想情况下,我想使用宏来生成大多数基本构造函数调用,但我必须为每个 COM 对象提供整个继承链;对于不同长度的链,这将需要不同的宏。但是,最长的长度是 4(我只使用 DXGI、D3D11 和 D2D1),所以这不是不可能的。

那么我怎样才能避免调用所有的构造函数呢?或者,有没有更好的方法来实现我想要做的事情?

【问题讨论】:

  • 对任何含糊/奇怪的陈述表示歉意;我在历史课的中间写了这个:P
  • C++ Wrapper Classes 类的历史?

标签: c++ inheritance constructor com virtual-inheritance


【解决方案1】:

事实证明,对于我想要完成的事情,CCOMWrapper 模板是不必要的。我只需要每个类提供一个构造函数来接受相应的 COM 对象类型:

class CDXGIObject : public CCOMObject
{
public:
    CDXGIObject(IDXGIObject *obj);
};

class CDXGIFactory : public CDXGIFactory
{
public:
    CDXGIFactory(IDXGIFactory *obj);
};

这消除了对虚拟继承的需要,因此我不再需要调用所有基本构造函数。

【讨论】:

    猜你喜欢
    • 2010-11-12
    • 2017-03-17
    • 2021-04-15
    • 2011-03-30
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    相关资源
    最近更新 更多