Implementing Multiple Interfaces in C++

Implementing multiple interfaces in c++

You can implement each individial interface using a separate template and then chain the templates to construct the derived object as if from building blocks. This method was also used by venerable ATL library to implement COM interfaces (for those of us old enough).

Note that you don't need virtual inheritance for that.

I slightly modified you example for a more complex derivation C -> B -> A to show how this method scales easily:

#include <stdio.h>

// Interfaces

struct A
{
virtual void foo() = 0;
};

struct B : A
{
virtual void testB() = 0;
};

struct C : B
{
virtual void testC() = 0;
};

// Implementations

template<class I>
struct AImpl : I
{
void foo() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct BImpl : I
{
void testB() { printf("%s\n", __PRETTY_FUNCTION__); }
};

template<class I>
struct CImpl : I
{
void testC() { printf("%s\n", __PRETTY_FUNCTION__); }
};

// Usage

int main() {
// Compose derived objects from templates as from building blocks.
AImpl<A> a;
BImpl<AImpl<B> > b;
CImpl<BImpl<AImpl<C> > > c;

a.foo();

b.foo();
b.testB();

c.foo();
c.testB();
c.testC();
}

Output:

void AImpl<I>::foo() [with I = A]
void AImpl<I>::foo() [with I = B]
void BImpl<I>::testB() [with I = AImpl<B>]
void AImpl<I>::foo() [with I = C]
void BImpl<I>::testB() [with I = AImpl<C>]
void CImpl<I>::testC() [with I = BImpl<AImpl<C> >]

How does implementing multiple COM interfaces work in C++?

Yes, there are multiple v-tables, one for each inherited interface. The static_cast<> returns it. The compiler makes sure that common methods in the inherited interfaces are shared, it fills each v-table slot with the a pointer to the same function. So you only need one implementation of AddRef, Release, QueryInterface. Just what you want. None of this is an accident.

This is only ever a problem when a coclass implements multiple interfaces with the same method that you don't want to give the same implementation. The IConnectionPoint::Advise() method is a notorious example. Or was it DAdvise()? Unfortunately, I don't remember what it clashed with and how it was solved, it was covered by ATL Internals. Very good book btw.

Best practise for implementing multiple interfaces in C#

Based on your comment:

I was hoping there was a better way then the obvious one. There will be a lot of code going into the realisation the the different interfaces, and the ILock interface does not really need to know about the ISavebale functionalty. I am basically looking for a clean way to do this that does not result in one class with 5k lines of code and 200 public functions

If you want a class to implement the interface the class will need to inherit the interface but the functionality could be injected and wrapped (aka Facade).

This would be the cleanest way to achieve your goal of generic but separate code classes for ISaveable, ILock etc.

For example:

public MyClass : IMyClass, ISaveable, ILock
{
private readonly ISaveable _saveableImplementation;
private readonly ILock _lockImplementation;

public MyClass(ISaveable saveableImplementation, ILock lockImplementation)
{
_saveableImplementation = saveableImplementation;
_lockImplementation - lockImplementation;
}

public void ISaveable.Save()
{
_saveableImplementation.Save();
}

public void ILock.Lock()
{
_lockImplementation.Lock();
}

}

implement multiple interfaces in C#

Inheritance of interfaces expresses the "is-a" relationship. You would inherit IEntity from IInterface1 if every implementation of IEntity must also be an IInterface1.

Yes: public interface IPanda : IBear

Probably not: public interface IAccountant : IObsessiveCompulsiveDisorder

Derived class implementing multiple interfaces with a common function signature

You need to define a common_func() anyway in MostDerivedClass to satisfy your inheritance from Interface2

you can try something like

virtual int common_func() {
return InterimClass::common_func();
}

This is most useful if you cannot change the first Interface1

If you want a real inheritance relationship between your classes you need to follow Lol4t0 advice. Extract a superclass from Interface1, and make Interface2 subclass of this newly created class. Example :

class RootInterface{
public :
virtual int common_func() = 0;
virtual ~RootInterface(){}
};

class Interface1 : public virtual RootInterface{
public:
virtual ~Interface1() {};
};

class Interface2 : public virtual RootInterface{
public:
virtual int new_func() = 0;
virtual ~Interface2() {};
};

class InterimClass : public Interface1 {
public:
virtual int common_func() {
return 10;
}
};

class MostDerivedClass : public InterimClass, public Interface2 {
public:
virtual int new_func() {
return 20;
}
};

Interfaces in C++, WITHOUT multiple inheritance

You can achieve almost the same result using template parameters:

template <typename TRAIT>
class ICommon
{
TRAIT t;

public: void Bind()
{
t.Bind();
}
}

class FooTrait
{
public: void Bind() { .... };
};

class BarTrait
{
public void Bind() { ..... }
}

typedef ICommon<FooTrait> Foo;
typedef ICommon<BarTrait> Bar;

template <typename T>
void call_bind(ICommon<T> x)
{
x.Bind();
}

int main()
{
Foo f; Bar b;
call_bind(f);
call_bind(b);
}

How can I express that an argument needs to implement multiple interfaces in C#

The solution I found here: How can I require a method argument to implement multiple interfaces? adjusted for C#.

Credits go to Michael Myers

internal interface IF1
{
void M1();
}

internal interface IF2
{
void M2();
}

internal class ClassImplementingIF1IF2 : IF1, IF2
{

public void M1()
{
throw new NotImplementedException();
}

public void M2()
{
throw new NotImplementedException();
}

}

internal static class Test
{

public static void doIT<T>(T t) where T:IF1,IF2
{
t.M1();
t.M2();
}

public static void test()
{
var c = new ClassImplementingIF1IF2();
doIT(c);
}
}

Why implementing multiple interfaces with same property shows 'ambiguity' warning?

Because the interface IAllYourBase does not declare the Percentage property itself.

When you assign an instance of AllYourBase to a variable of IAllYourBase the compiler needs to output a call to either IBase1.Percentage or IBase2.Percentage:

callvirt   instance int32 IBase1::get_Percentage()

or

callvirt   instance int32 IBase2::get_Percentage()

These are different members on different types and just because they have the same signature doesn't mean they are interchangeable.

In your real world situation you might need finer grained interfaces that define the common properties.



Related Topics



Leave a reply



Submit