2

I was wondering what was the best way to achieve code reuse by inheritance in a COM application.

The Problem

It came to my understanding that the virtual inheritance model of C++ cannot by used in a COM environment because it is not language independent.

In pure C++ a class hierarchy could look something like the following:

interface IBase {
    virtual void BaseMethod() = 0;
};

interface IDerived : virtual IBase {
    virtual void DerivedMethod() = 0;
};

class CBase : public virtual IBase {
public:
    virtual void BaseMethod() override { /* Do something */ }
};

class CDerived : public IDerived, public CBase {
public:
    virtual void DerivedMethod() override { /* Do something */ }
};

This results in the following hierarchy:

class hierarchy with virtual inheritance

IDerived and CBase both inherit virtually from IBase.

Since virtual inheritance is not available in COM, the class hierarchy would rather look something like this:

interface IBase {
    virtual void BaseMethod() = 0;
};

interface IDerived : IBase {
    virtual void DerivedMethod() = 0;
};

class CBase : public IBase {
public:
    virtual void BaseMethod() override { /* Do something */ }
};

class CDerived : public IDerived, public CBase {
public:
    virtual void DerivedMethod() override { /* Do something */ }
};

This results in the following hierarchy:

class hierarchy without virtual inheritance

At first glance, there seems to be a problem with the ambiguity of IBase. This can be easily resolved by implementing the IUnknown::QueryInterface method.

The real problem is, how can CDerived inherit the implemented methods of IBase from CBase, namely CBase::BaseMethod?

In the case of virtual inheritance, CBase::BaseMethod can be inherited by dominance, but without virtual inheritance this cannot happen: In CDerived, the method CBase::IBase::BaseMethod is defined, however the method IDerived::IBase::BaseMethod is not, resulting in the class CBase still being abstract and not thus not eligible for instantiation.

One way, to resolve this would be to override the method BaseMethod in CDerived once again:

class CDerived : public IDerived, public CBase {
public:
    virtual void BaseMethod() override { CBase::BaseMethod(); }
    virtual void DerivedMethod() override { /* Do something */ }
};

Does this have any performance implications? Is there a better way of achieving what I want? Doesn't the repeated override of the function in CDerived defeat the whole idea of inheritance?

1
  • This question is based on a very broken assumption. COM achieves language independence by the client code only ever seeing interfaces. The implementation is completely invisible. That allows you to do anything you want to implement the interfaces, and in fact using non-virtual multiple inheritance is the boilerplate approach. Having only one function to implement QueryInterface, AddRef, Release for all the implemented interfaces is exactly what you want. Any basic tutorial for COM shows you how to do that. Commented Mar 3, 2017 at 13:45

1 Answer 1

2

ATL widely uses a technique that goes like this:

template <typename Itf>
class IBaseImpl : public Itf {
public:
  void BaseMethod() override;
};

class CBase : public IBaseImpl<IBase> {};

class CDerived : public IBaseImpl<IDerived> {
public:
  void DerivedMethod() override;
};

Now you have straight-line inheritance: IBase <- IDerived <- IBaseImpl<IDerived> <- CDerived.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.