How do I setup a class that represents an interface? Is this just an abstract base class?
In C++11 you can easily avoid inheritance altogether:
struct Interface {
explicit Interface(SomeType& other)
: foo([=](){ return other.my_foo(); }),
bar([=](){ return other.my_bar(); }), /*...*/ {}
explicit Interface(SomeOtherType& other)
: foo([=](){ return other.some_foo(); }),
bar([=](){ return other.some_bar(); }), /*...*/ {}
// you can add more types here...
// or use a generic constructor:
template
explicit Interface(T& other)
: foo([=](){ return other.foo(); }),
bar([=](){ return other.bar(); }), /*...*/ {}
const std::function foo;
const std::function bar;
// ...
};
In this case, an Interface has reference semantics, i.e. you have to make sure that the object outlives the interface (it is also possible to make interfaces with value semantics).
These type of interfaces have their pros and cons:
Finally, inheritance is the root of all evil in complex software design. In Sean Parent's Value Semantics and Concepts-based Polymorphism (highly recommended, better versions of this technique are explained there) the following case is studied:
Say I have an application in which I deal with my shapes polymorphically using the MyShape
interface:
struct MyShape { virtual void my_draw() = 0; };
struct Circle : MyShape { void my_draw() { /* ... */ } };
// more shapes: e.g. triangle
In your application, you do the same with different shapes using the YourShape
interface:
struct YourShape { virtual void your_draw() = 0; };
struct Square : YourShape { void your_draw() { /* ... */ } };
/// some more shapes here...
Now say you want to use some of the shapes that I've developed in your application. Conceptually, our shapes have the same interface, but to make my shapes work in your application you would need to extend my shapes as follows:
struct Circle : MyShape, YourShape {
void my_draw() { /*stays the same*/ };
void your_draw() { my_draw(); }
};
First, modifying my shapes might not be possible at all. Furthermore, multiple inheritance leads the road to spaghetti code (imagine a third project comes in that is using the TheirShape
interface... what happens if they also call their draw function my_draw
?).
Update: There are a couple of new references about non-inheritance based polymorphism: