C++ pure virtual multiple inheritance?

2019-04-21 06:58发布

问题:

I need help for an implementation that uses multiple inheritance of Interfaces...

There is an existing code whith an interface which has a lot of functions. The instances are created using a factory.

class IBig
{
    // Lot of pure virtual functions
};

And his inplementation:

class CBig: public IBig
{
    // Implementation
}

I Want to split the interface in multiple smaller interfaces, but it should stay compatible to the existing code for some time.

Here is a sample of what I tried to do:

class IBaseA
{
public:
    virtual void DoA() = 0;
};

class IBaseB
{
public:
    virtual void DoB() = 0;
};

// The same interface, now based on multiple smaller interfaces
class IBig : public IBaseA, public IBaseB
{
};

class CBaseA: public IBaseA
{
public:
    virtual void DoA()
    {
        printf("DoA\n");
    }
};

class CBaseB: public IBaseB
{
public:
    virtual void DoB()
    {
        printf("DoB\n");
    }
};

// Inherit from base classes where the implementation is, and from IBig as 
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};

The problem here is that the class CBig cannot be instanciated. The compiler says the functions DoA and DoB are pure virtual, even if they are inplemented in CBaseA and CBaseB. What should I do if i don't want to implement again the functions, just to call the function of the base class ?

NB: I know the design is ugly, but this is only temporary until the big interface can be replaced, and.... I want to understand ! ;-)

Thanks in advance !

回答1:

Here you should use virtual inheritance. This feature assures that there is only one instance of your virtually-inherited base class when you instantiate a subclass. For your example, this would look like:

#include <cstdio>

class IBaseA
{
public:
    virtual void DoA() = 0;
};

class IBaseB
{
public:
    virtual void DoB() = 0;
};

// The same interface, now based on multiple smaller interfaces
class IBig : virtual public IBaseA,  virtual public IBaseB
//              ^                       ^
{
};

class CBaseA: virtual public IBaseA
//              ^
{
public:
    virtual void DoA()
    {
        printf("DoA\n");
    }
};

class CBaseB: virtual public IBaseB
//              ^
{
public:
    virtual void DoB()
    {
        printf("DoB\n");
    }
};

// Inherit from base classes where the implementation is, and from IBig as 
// the instance of CBig is returned as IBig.
class CBig: public CBaseA, public CBaseB, public IBig
{
};

int main()
{
    CBig cb;
}

The above changes ensure that there are not extra declarations of DoA and DoB created when you inherit from IBaseA and IBaseB multiple times.



回答2:

This is known as the deadly diamond of death (or simply diamond problem). It occurs because CBig inherits from classes that share common base classes.

You can either call the correct DoA by prefixing it with the class it belongs to

CBaseA::doA();

or you use virtual inheritance to only have one instance of IBaseA and IBaseB

class CBaseA : public virtual IBaseA {};
class CBaseB : public virtual IBaseB {};
class IBig : public virtual IBaseA, public virtual IBaseB {};

and so on...