Basic question: is it possible to avoid having to explicitly call the (non-default) constructor of every virtual base class?
Background: I'm working on some type-safe C++ wrapper classes around Windows COM objects. My current approach is to have a CBaseCOMWrapper
class which encapsulates an IUnknown
object for reference counting. Then, I have a CCOMWrapper
template class which inherits from CBaseCOMWrapper
, which defines a wrapper for specific COM types (i.e. IDXGIObject
, ID3D11Device
, etc). Finally, separate classes inherit from these wrapper templates to provide actual/extra functionality (i.e. CDXGIObject
, CD3D11Device
).
For example, I have the following classes (members omitted):
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> { };
Here's the corresponding diagram of the type hierarchy:
The left column is the actual objects, the middle column the thin COM wrappers, and the right column the actual COM objects. Solid arrows denote inheritance, and dashed arrows denote encapsulation.
I use template specializations of CCOMWrapper
to provide the parent-child relationships in the middle.
Problem: The wrapper classes assume a non-NULL (aka valid) pointer to a COM object, so I can't have a default constructor. Because the hierarchy is full of "diamonds", much of the inheritance is virtual; this means each class's constructor must call the constructor. So, in the example above, the constructor of CDXGIAdapter
must call the constructors of CCOMWrapper<IDXGIAdapter>
, CDXGIObject
, CCOMWrapper<IDXGIObject>
, and CBaseCOMWrapper
. As the hierarchy expands (i.e. ID3D11Predicate
's inheritance chain is 4 "links" long), this means more constructors must be called.
Possible solution: Ideally, I'd like to use macros to generate most of the base constructor calls, but I'd have to provide the entire inheritance chain for each COM object; this would require different macros for chains of different lengths. However, the longest such length is 4 (I'm only working with DXGI, D3D11, and D2D1), so this isn't out of the question.
So how can I avoid having to call all the constructors? Alternatively, is there a better way to achieve what I'm trying to do?
So, Don't invoke virtual functions from constructors or destructors that attempts to call into the object under construction or destruction, Because the order of construction starts from base to derived and the order of destructors starts from derived to base class.
You can call a virtual function in a constructor, but be careful. It may not do what you expect. In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn't yet happened. Objects are constructed from the base up, “base before derived”.
Constructor can not be virtual, because when constructor of a class is executed there is no vtable in the memory, means no virtual pointer defined yet. Hence the constructor should always be non-virtual.
In C++, the constructor cannot be virtual, because when a constructor of a class is executed there is no virtual table in the memory, means no virtual pointer defined yet. So, the constructor should always be non-virtual. But virtual destructor is possible.
So as it turns out, for what I want to accomplish, the CCOMWrapper
template is unnecessary. I just need each class to provide a constructor that takes the corresponding COM object type:
class CDXGIObject : public CCOMObject
{
public:
CDXGIObject(IDXGIObject *obj);
};
class CDXGIFactory : public CDXGIFactory
{
public:
CDXGIFactory(IDXGIFactory *obj);
};
This eliminates the need for virtual inheritance, thus I don't need to call all of the base constructors anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With