【发布时间】:2014-09-09 15:18:24
【问题描述】:
基本问题:是否可以避免显式调用每个虚拟基类的(非默认)构造函数?
背景:我正在研究一些围绕 Windows COM 对象的类型安全的 C++ 包装类。我目前的方法是有一个CBaseCOMWrapper 类,它封装了一个IUnknown 对象以进行引用计数。然后,我有一个从CBaseCOMWrapper 继承的CCOMWrapper 模板类,它为特定的COM 类型(即IDXGIObject、ID3D11Device 等)定义了一个包装器。最后,独立的类从这些包装模板继承以提供实际/额外的功能(即CDXGIObject、CD3D11Device)。
例如,我有以下类(成员省略):
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<IDXGIAdapter>、CDXGIObject、CCOMWrapper<IDXGIObject>和CBaseCOMWrapper的构造函数。随着层次结构的扩展(即ID3D11Predicate 的继承链有 4 个“链接”长),这意味着必须调用更多的构造函数。
可能的解决方案:理想情况下,我想使用宏来生成大多数基本构造函数调用,但我必须为每个 COM 对象提供整个继承链;对于不同长度的链,这将需要不同的宏。但是,最长的长度是 4(我只使用 DXGI、D3D11 和 D2D1),所以这不是不可能的。
那么我怎样才能避免调用所有的构造函数呢?或者,有没有更好的方法来实现我想要做的事情?
【问题讨论】:
-
对任何含糊/奇怪的陈述表示歉意;我在历史课的中间写了这个:P
-
C++ Wrapper Classes 类的历史?
标签: c++ inheritance constructor com virtual-inheritance