基本问题:是否可以避免必须显式调用每个虚拟基类的(非默认)构造函数?
后台:我正在开发围绕Windows COM对象的一些类型安全的C ++包装器类。我目前的方法是使用CBaseCOMWrapper
类来封装IUnknown
对象以进行引用计数。然后,我有一个CCOMWrapper
模板类,它继承自CBaseCOMWrapper
,它定义了特定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),所以这不是不可能的。
那么如何避免必须调用所有构造函数?或者,有没有更好的方法来实现我想要做的事情?
答案 0 :(得分:1)
事实证明,对于我想要完成的事情,CCOMWrapper
模板是不必要的。我只需要每个类提供一个构造函数,该构造函数采用相应的COM对象类型:
class CDXGIObject : public CCOMObject
{
public:
CDXGIObject(IDXGIObject *obj);
};
class CDXGIFactory : public CDXGIFactory
{
public:
CDXGIFactory(IDXGIFactory *obj);
};
这消除了对虚拟继承的需要,因此我不再需要调用所有基础构造函数。