避免显式构造函数调用虚拟基类

时间:2014-09-09 15:18:25

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

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

后台:我正在开发围绕Windows COM对象的一些类型安全的C ++包装器类。我目前的方法是使用CBaseCOMWrapper类来封装IUnknown对象以进行引用计数。然后,我有一个CCOMWrapper模板类,它继承自CBaseCOMWrapper,它定义了特定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> { };

以下是类型层次结构的对应图表:

Type Hierarchy

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

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

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

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

那么如何避免必须调用所有构造函数?或者,有没有更好的方法来实现我想要做的事情?

1 个答案:

答案 0 :(得分:1)

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

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

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

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