Interface design and inheritance in C ++

I need to use C ++ interface classes to implement an unmanaged DLL in C ++. Suppose I have this class structure:

class IA
{
public:

    virtual void Foo() = 0;
    ...
};

class A : public IA
{
public:

    virtual void Foo() override { ... }
    ...
};

class IB
{
public:

    virtual void Bar() = 0;
    ...
};

class B : public IB
    , public A
{
public:

    virtual void Bar() { ... }
    ...
};

      

Now if I have a pointer to an interface IB

, this won't compile:

IB* b = ...;
b->Foo();

      

To make it work, I need to do IB

inheritance from IA

, as such:

class IB : public IA
{
    ...
};

      

But then this also won't compile because it is B

no longer a concrete class anymore and the compiler is expecting to implement IA::Foo

it even if it inherits from A

.

You can fix this with virtual inheritance:

class A : public virtual IA { ... };
class IB : public virtual IA { ... };
class B : public virtual IB, public A { ... };

      

Which generates a new warning in VC ++:

warning C4250: 'B' : inherits 'A::A::Foo' via dominance

      

As I understand it, this is because there is now more than one ad Foo

.

How to inherit interfaces and their concrete implementation correctly without these problems?

+3


source to share


4 answers


Suppress C4250 in compiler settings and forget about it.



I don't know of any problems with inheritance through dominance. The other compilers I use never warn about this, even at the highest warning levels. Googling for c++ inheritance dominance problem

only raises complaints about the C4250, never describing any real problem with the actual code. I believe this is not a problem.

+1


source


As you wrote, this does not compile:

IB* b = ...;
b->Foo();

      

Of course this won't compile as IB

it has no member Foo

. To access Foo

, you will need a pointer to IA

, but IB*

cannot be added to IA*

.

But there is a point where you get a pointer to IB

. At this point (or somewhere up the line) some interface needs to know about the true object B

, which can also be added to other IA

than IB

. At this point, you can request IA*

and use it as such.

Someone who has IB*

may not even know if the implementation is IB

also IA

, or not.




Another possibility would be to define a caste member on IB

, which discards your pointer to IA*

. Like this:

IA * GetAsIA() = 0;

      

IB

implementations that IA

can also return a valid pointer, other implementations can return nullptr.

+2


source


Not IB

trying to implement IA

anywhere else yet, but A

, and you realize you B

have an implementation IB

that depends on the implementation A

(since the B

implementation is IA

implemented with A

), you can safely ignore this warning.

The main reason for the warning is that you usually need to search up or down the inheritance hierarchy to find all implementations, however in this case you need to look away from IB

to A

.

0


source


If you want to remove the warning, the Suppressing C4250 answers in your compiler are an option.

However, I think you have a bad design.

  • Your class "B" depends on the specific class (class "A").
  • You are using multiple inheritance. This is very few times a good solution.

I think you should try to connect Has-a instead of Is-a .

class IA
{
public:
    virtual void Foo() = 0;
    ...
};

class A : public IA
{
public:
    virtual void Foo() override { ... }
    ...
};

class IB
{
public:
    virtual void Bar() = 0;
    ...
};

class B : public IB
{
private:
    IA* ptrIA;
public:
    B(IA* ia): ptrIA(ia) {}

    virtual void Bar() { ... }
    void performeFoo() { ptrIA->Foo(); }
    ...
};

      

0


source







All Articles