I'm asked to implement an interface and I'm wondering what would be the best strategy to factorize the code as much as possible.
Here is the interface definition (I'm not supposed to change it):
#include <string>
class BaseIf
{
public:
virtual ~BaseIf() {}
virtual std::string getName() = 0;
};
class IntIf : public BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
};
class FloatIf : public BaseIf
{
public:
virtual ~FloatIf() {}
virtual float getValue() = 0;
};
I'll end up with IntImpl (implementing IntIf) and FloatImpl (implementing FloatIf). But I'm wondering where I should put any code common to those two classes (like the name attribute management or any other stuff required by BaseIf which is actually much bigger than in this MCVE).
If I create BaseImpl (implementing BaseIf's getName function) with the common code, and have IntImpl derive from it (and IntIf), then I need to also implement getName in it because it's reported as not implemented. And I also get double inheritance of BaseIf...
I was wondering if Pimpl pattern would help, then IntImpl would have a BaseImpl object as attribute (and only derive from IntIf), but then, again, I need to implement getName in IntImpl to "forward" the call to the BaseImpl attribute. So as BaseIf has actually many virtual functions this is just going to be a real pain to maintain.
Is there no smart solution/pattern making it possible to implement once only getName in a common place? Or is it just the interface that is bad and should be reworked?
This is the primary use case for virtual inheritance.
Despite all the stigma that surrionds multiple and virtual inheritance, there are no particular problems when oure interfaces (no data members) are virtually inherited. Here's the gist:
class BaseIf
{
public:
virtual ~BaseIf() {}
virtual std::string getName() = 0;
};
class IntIf : public virtual BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
};
class BaseImpl : public virtual BaseIf
{
public:
std::string getName () override { return "whoa dude"; }
};
class IntImpl : public virtual IntIf, public BaseImpl
{
public:
int getValue() override { return 42; }
};
full demo
With a deeper hierarchy one probably would have to virtually inherit implementation classes as well, which is not very convenient but still doable.
An alternative to virtual inheritance of implementation would be to stratify the implementation into a "building blocks" layer and the final layer. Building blocks are standalone and do not inherit other building blocks. (They may inherit interfaces). The final classes inherit building blocks but not other final classes.
class BaseBlock : public virtual BaseIf
{
public:
std::string getName () override { return "whoa dude"; }
};
class IntBlock : public virtual IntIf
{
public:
int getValue() override { return 42; }
};
class BaseImpl : public BaseBlock {};
class IntImpl : public BaseBlock, public IntBlock {};
full demo
One does need to made changes to the interfaces if there was no virtual inheritance in the hierarchy. These changes are however transparent (the clients code need not be changed, only recompiled) and probably beneficial anyway.
Without virtual inheritance, one would have to resort to lots of boilerplate.
class BaseBlock // no base class!
{
public:
virtual std::string getName () { return "whoa dude"; }
};
class BaseImpl : public BaseIf, public BaseBlock
{
public:
// oops, getName would be ambiguous here, need boplerplate
std::string getName () override { return BaseBlock::getName(); }
};
You can make a template class that implements the common part of an interface like this:
template <class IFACE> class BaseImpl : public IFACE
{
public:
std::string getName () override { ... }
}
and then
class IntImpl : public BaseImpl<IntIf>
{
public:
int getValue() override { ... }
}
The result is a simple single-inheritance chain. BaseIf <- IntIf <- BaseImpl <- IntImpl
Make sure you have a good reason for IntIf and FloatIf to exist, though -- in your MCVE they look like they don't need to be there at all.
You can provide default implementation for pure virtual functions:
struct A {
virtual void frob() = 0;
};
void A::frob() {
std::cout << "default";
}
struct B : A {
void frob() override {
A::frob(); // calls the default
}
};
If I'm reading your problem correctly, you'd like a default implementation for getName(). So solve that, simply provide an implementation and call it:
class IntIf : public BaseIf
{
public:
virtual ~IntIf() {}
virtual int getValue() = 0;
std::string getName() override {
return BaseIf::getName();
}
};
class FloatIf : public BaseIf
{
public:
virtual ~FloatIf() {}
virtual float getValue() = 0;
std::string getName() override {
return BaseIf::getName();
}
};
Related
I have two interfaces:
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
This is a combined interface:
class CombinedInterface : public FirstInterface, public SecondInterface
{
};
This is a concrete class of first interface:
class FirstConcrete : public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
Now, this class CompleteConcrete should have the CombinedInterface but want to reuse the implementation of FirstConcrete at the same time.
class CompleteConcrete : public FirstConcrete, public SecondInterface
{
virtual void setId(int id) { }
};
// This is wrong C++
// Cannot convert from CompleteConcrete * to CombinedInterface *
// CombinedInterface * combinedInterface = new CompleteConcrete();
This is not working of course. Does anyone know a way to achieve this goal in C++ ??
Here's the virtual-inheritance based solution that I mentioned in the comments:
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
class CombinedInterface : virtual public FirstInterface,
virtual public SecondInterface
{
};
class FirstConcrete : virtual public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
class CompleteConcrete : virtual public FirstConcrete,
virtual public CombinedInterface
{
virtual void setId(int id) { }
};
void example()
{
CombinedInterface * combinedInterface = new CompleteConcrete();
}
With virtual inheritance, the only change that's needed (besides the elephant in the room) is to have CompleteConcrete multiply-inherit from CombinedInterface, instead of SecondInterface. You can think of it this way: with CompleteConcreate in the picture, it now supports CombinedInterface, and not just the addition of SecondInterface.
Some frown on virtual inheritance. I don't. It's one of the unique features of C++, that no other high level language shared, TMK. It's a very powerful tool, and can solve certain problems that would be hard to solve in other ways. The two main disadvantages of virtual inheritance are:
Because it is so powerful, it can be easily misused, and lead to various problems.
If virtually-inherited classes have non-default constructors it quickly becomes painful, because every class that virtually inherits something is now responsible for constructing it.
But as long as virtual inheritance is used correctly, and the involved classes can take of constructing themselves, virtual inheritance is a useful tool.
P.S. I'll also mention one other alternative solution that just came to mind. If, say you have your CombinedInterface just so that it can be required for some particular function, like:
void somefunction(CombinedInterface &object);
Your function requires a combined interface.
Make a small change:
void somefunction(FirstInterface &first, SecondInterface &second);
and pass the same object as both parameters. You can pass CompleteConcrete, that implements both interfaces, without any changes to your class hierarchy. You could also have a template facade that makes it look like the function still takes one parameter:
template<typename T> void somefunction(T &&t)
{
real_somefunction(std::forward<T>(t), std::forward<T>(t));
}
void real_somefunction(FirstInterface &first, SecondInterface &second);
You can pretty much get rid of CombinedInterface, and simply pass any object that implements both interfaces to somefunction(), and your real_somefunction() will use one or the other parameter to invoke the appropriate interface.
Say you need to carry a pointer to an object that implements both interfaces?
class combined_pointer : public std::pair<FirstInterface *, SecondInterface *> {
public:
template<typename T> combined_pointer(T *t)
: std::pair<FirstInterface *, SecondInterface *>(t, t)
{}
};
Just a starting point.
I've used virtual inheritance.
This compiled successfully with a warning, but I think it is ok.
class FirstInterface
{
virtual int getId() const = 0;
};
class SecondInterface
{
virtual void setId(int id) = 0;
};
class CombinedInterface : virtual public FirstInterface, public SecondInterface
{
};
class FirstConcrete : virtual public FirstInterface
{
virtual int getId() const
{
return 1;
}
};
class CompleteConcrete : public CombinedInterface, public FirstConcrete
{
virtual void setId(int id) { }
};
// warning: C4250: inherits via dominance
CombinedInterface * combinedInterface = new CompleteConcrete();
Let a class hierarchy :
class Base { virtual ~Base() throw(); };
class DerivedA : public Base { };
class DerivedB : public Base { };
I would like to have some code specific to each of these derived classes. However that code also being specific to the application that makes use of this class hierarchy, I do not want to embbed this derived-class-specific code into these derived classes. To avoid doing so, I thought about writing free functions :
void DerivedASpecificWork( DerivedA da );
void DerivedBSpecificWork( DerivedB db );
However, when given an instance of a derived class through a reference/pointer to a Base, I do not have access to the actual type of the instance, and thus cannot call the proper Derived*SpecificWork() function.
I would like to know if there is nome kind of design pattern that would allow me to call a derived-class-specific function without knowing the actual type of the instance, i.e having the same mechanism as virtual functions provide, but without having these virtual functions that would require me to embbed application-specific code into that class hierarchy.
Actually, why I want to do that is to provide informations about an exception that occured within a natively implemented function called by a Lua script. Each exception carrying its own set of information, the way I want to represent the error within the script depends on the type of the exception. I could create a pure virtual method in the base class that would be implemented by derived classes, but this would require me to embbed Lua-related code into my exception hierarchy, which I do not want to do since the Lua is specific to one of the application using that exception hierarchy.
Also I cannot use C++11.
Thank you.
May be Brigde pattern can help you.
This pattern can be used when you want to avoid a permanent binding between an abstraction and it's implementation.
(I don't see your comment about your restriction in using c++11, but you can remove std::unique_ptr, std::move and override keyword)
class AppSpecificImp
{
public:
virtual void DoWork() = 0;
};
class Base
{
public:
virtual ~Base() throw();
virtual DoWork() = 0;
};
class DerivedA : public Base
{
public:
DerivedA(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedA specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
class DerivedB : public Base
{
public:
DerivedB(std::unique_ptr<AppSpecificImp> appImp)
: imp(std::move(appImp))
{
}
void DoWork() override
{
// DerivedB specific code
imp->DoWork();
}
private:
std::unique_ptr<AppSpecificImp> imp;
};
Edit to show Visitor pattern usage:
With visitor pattern you can do what you want but with more Effort.
class Visitor
{
public:
virtual void VisitDerivedA(DerivedA* object) = 0;
virtual void VisitDerivedB(DerivedB* object) = 0;
};
class Base
{
public:
virtual void Visit(Visitor* visitor) = 0;
};
class DerivedA : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedA(this);
}
};
class DerivedB : public Base
{
public:
virtual void Visit(Visitor* visitor)
{
visitor->VisitDerivedB(this);
}
};
class AppSpecificVisitor : public Visitor
{
public:
void VisitDerivedA(DerivedA* object)
{
// Do any work related to DerivedA class
}
void VisitDerivedB(DerivedB* object)
{
// Do any work related to DerivedB class
}
}
int main()
{
AppSpecificVisitor myVisitor;
Base* myBase = // any class in your hierarchy
myBase->Visit(&myVisitor);
}
As I said in comments with Visitor pattern you can add new functionally without changing the main hierarchy(Base->Derived types). You just define a new visitor implementation and write your logic for every class in main hierarchy. In your example you can pack app specific logic in an object and reference that in your derived objects that is an easier approach.
Why not using a new set of hierarchy for application specific implementation ?
class AppBase
{
public:
virtual ~AppBase() throw();
virtual void work_with_app() = 0;
};
class Base
{
public:
Base(AppBase& app) : m_app(app) {}
virtual ~Base() throw();
protected:
AppBase& m_app;
};
class DerivedA : public Base { DerivedA(AppBase& app) : Base(app) {} };
class DerivedB : public Base { DerivedA(AppBase& app) : Base(app) {} };
// Application specific implementation :
class AppLuaSpecific : public AppBase
{
public:
void work_with_app() { /* Lua app specific */ }
};
This way, your 1st hierarchy : Base, DerivedA, DerivedB can live without knowing anything about the app specific code implemented in AppLuaSpecific.
You can implement your own app-specific dispatch as follows (check it live on Coliru):
#include <iostream>
#include <typeinfo>
struct Base { virtual ~Base() {} };
struct DerivedA : public Base { };
struct DerivedB : public Base { };
namespace AppSpecific
{
template<class F>
void dispatch(const Base& b)
{
const std::type_info& t = typeid(b);
if ( t == typeid(DerivedA) )
F::doit(static_cast<const DerivedA&>(b));
else if ( t == typeid(DerivedB) )
F::doit(static_cast<const DerivedB&>(b));
}
struct Foo
{
static void doit(const DerivedA& da) { std::cout << "Foo(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Foo(DerivedB)\n"; }
};
struct Bar
{
static void doit(const DerivedA& da) { std::cout << "Bar(DerivedA)\n"; }
static void doit(const DerivedB& db) { std::cout << "Bar(DerivedB)\n"; }
};
} // namespace AppSpecific
int main()
{
DerivedA da;
DerivedB db;
Base& b1 = da;
Base& b2 = db;
AppSpecific::dispatch<AppSpecific::Foo>(b1);
AppSpecific::dispatch<AppSpecific::Foo>(b2);
AppSpecific::dispatch<AppSpecific::Bar>(b1);
AppSpecific::dispatch<AppSpecific::Bar>(b2);
}
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 !
Here we 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.
There are two base classes have same function name. I want to inherit both of them, and over ride each method differently. How can I do that with separate declaration and definition (instead of defining in the class definition)?
#include <cstdio>
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2
{
public:
virtual void Name() = 0;
};
class RealClass: public Interface1, public Interface2
{
public:
virtual void Interface1::Name()
{
printf("Interface1 OK?\n");
}
virtual void Interface2::Name()
{
printf("Interface2 OK?\n");
}
};
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
I failed to move the definition out in VC8. I found the Microsoft Specific Keyword __interface can do this job successfully, code below:
#include <cstdio>
__interface Interface1{
virtual void Name() = 0;
};
__interface Interface2
{
virtual void Name() = 0;
};
class RealClass: public Interface1,
public Interface2
{
public:
virtual void Interface1::Name();
virtual void Interface2::Name();
};
void RealClass::Interface1::Name()
{
printf("Interface1 OK?\n");
}
void RealClass::Interface2::Name()
{
printf("Interface2 OK?\n");
}
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
but is there another way to do this something more general that will work in other compilers?
This problem doesn't come up very often. The solution I'm familiar with was designed by Doug McIlroy and appears in Bjarne Stroustrup's books (presented in both Design & Evolution of C++ section 12.8 and The C++ Programming Language section 25.6). According to the discussion in Design & Evolution, there was a proposal to handle this specific case elegantly, but it was rejected because "such name clashes were unlikely to become common enough to warrant a separate language feature," and "not likely to become everyday work for novices."
Not only do you need to call Name() through pointers to base classes, you need a way to say which Name() you want when operating on the derived class. The solution adds some indirection:
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2{
public:
virtual void Name() = 0;
};
class Interface1_helper : public Interface1{
public:
virtual void I1_Name() = 0;
void Name() override
{
I1_Name();
}
};
class Interface2_helper : public Interface2{
public:
virtual void I2_Name() = 0;
void Name() override
{
I2_Name();
}
};
class RealClass: public Interface1_helper, public Interface2_helper{
public:
void I1_Name() override
{
printf("Interface1 OK?\n");
}
void I2_Name() override
{
printf("Interface2 OK?\n");
}
};
int main()
{
RealClass rc;
Interface1* i1 = &rc;
Interface2* i2 = &rc;
i1->Name();
i2->Name();
rc.I1_Name();
rc.I2_Name();
}
Not pretty, but the decision was it's not needed often.
You cannot override them separately, you must override both at once:
struct Interface1 {
virtual void Name() = 0;
};
struct Interface2 {
virtual void Name() = 0;
};
struct RealClass : Interface1, Interface2 {
virtual void Name();
};
// and move it out of the class definition just like any other method:
void RealClass::Name() {
printf("Interface1 OK?\n");
printf("Interface2 OK?\n");
}
You can simulate individual overriding with intermediate base classes:
struct RealClass1 : Interface1 {
virtual void Name() {
printf("Interface1 OK?\n");
}
};
struct RealClass2 : Interface2 {
virtual void Name() {
printf("Interface2 OK?\n");
}
};
struct RealClass : RealClass1, RealClass2 {
virtual void Name() {
// you must still decide what to do here, which is likely calling both:
RealClass1::Name();
RealClass2::Name();
// or doing something else entirely
// but note: this is the function which will be called in all cases
// of *virtual dispatch* (for instances of this class), as it is the
// final overrider, the above separate definition is merely
// code-organization convenience
}
};
Additionally, you're using reinterpret_cast incorrectly, you should have:
int main() {
RealClass rc; // no need for dynamic allocation in this example
Interface1& one = rc;
one.Name();
Interface2& two = dynamic_cast<Interface2&>(one);
two.Name();
return 0;
}
And here's a rewrite with CRTP that might be what you want (or not):
template<class Derived>
struct RealClass1 : Interface1 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface1 for %s\n", self.name.c_str());
}
#undef self
};
template<class Derived>
struct RealClass2 : Interface2 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface2 for %s\n", self.name.c_str());
}
#undef self
};
struct RealClass : RealClass1<RealClass>, RealClass2<RealClass> {
std::string name;
RealClass() : name("real code would have members you need to access") {}
};
But note that here you cannot call Name on a RealClass now (with virtual dispatch, e.g. rc.Name()), you must first select a base. The self macro is an easy way to clean up CRTP casts (usually member access is much more common in the CRTP base), but it can be improved. There's a brief discussion of virtual dispatch in one of my other answers, but surely a better one around if someone has a link.
I've had to do something like this in the past, though in my case I needed to inherit from one interface twice and be able to differentiate between calls made on each of them, I used a template shim to help me...
Something like this:
template<class id>
class InterfaceHelper : public MyInterface
{
public :
virtual void Name()
{
Name(id);
}
virtual void Name(
const size_t id) = 0;
}
You then derive from InterfaceHelper twice rather than from MyInterface twice and you specify a different id for each base class. You can then hand out two interfaces independently by casting to the correct InterfaceHelper.
You could do something slightly more complex;
class InterfaceHelperBase
{
public :
virtual void Name(
const size_t id) = 0;
}
class InterfaceHelper1 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(1);
}
}
class InterfaceHelper2 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(2);
}
}
class MyClass : public InterfaceHelper1, public InterfaceHelper2
{
public :
virtual void Name(
const size_t id)
{
if (id == 1)
{
printf("Interface 1 OK?");
}
else if (id == 2)
{
printf("Interface 2 OK?");
}
}
}
Note that the above hasn't seen a compiler...
class BaseX
{
public:
virtual void fun()
{
cout << "BaseX::fun\n";
}
};
class BaseY
{
public:
virtual void fun()
{
cout << "BaseY::fun\n";
}
};
class DerivedX : protected BaseX
{
public:
virtual void funX()
{
BaseX::fun();
}
};
class DerivedY : protected BaseY
{
public:
virtual void funY()
{
BaseY::fun();
}
};
class DerivedXY : public DerivedX, public DerivedY
{
};
There are two other related questions asking nearly (but not completely) identical things:
Picking from inherited shared method names. If you want to have rc.name() call ic1->name() or ic2->name().
Overriding shared method names from (templated) base classes. This has simpler syntax and less code that your accepted solution, but does not allow for access to the functions from the derived class. More or less, unless you need to be able to call name_i1() from an rc, you don't need to use things like InterfaceHelper.
I have the following class structure:
class InterfaceA
{
virtual void methodA =0;
}
class ClassA : public InterfaceA
{
void methodA();
}
class InterfaceB : public InterfaceA
{
virtual void methodB =0;
}
class ClassAB : public ClassA, public InterfaceB
{
void methodB();
}
Now the following code is not compilable:
int main()
{
InterfaceB* test = new ClassAB();
test->methodA();
}
The compiler says that the method methodA() is virtual and not implemented. I thought that it is implemented in ClassA (which implements the InterfaceA).
Does anyone know where my fault is?
That is because you have two copies of InterfaceA. See this for a bigger explanation: https://isocpp.org/wiki/faq/multiple-inheritance (your situation is similar to 'the dreaded diamond').
You need to add the keyword virtual when you inherit ClassA from InterfaceA. You also need to add virtual when you inherit InterfaceB from InterfaceA.
Virtual inheritance, which Laura suggested, is, of course, the solution of the problem. But it doesn't end up in having only one InterfaceA. It has "side-effects" too, for ex. see https://isocpp.org/wiki/faq/multiple-inheritance#mi-delegate-to-sister. But if get used to it, it may come in handy.
If you don't want side effects, you may use template:
struct InterfaceA
{
virtual void methodA() = 0;
};
template<class IA>
struct ClassA : public IA //IA is expected to extend InterfaceA
{
void methodA() { 5+1;}
};
struct InterfaceB : public InterfaceA
{
virtual void methodB() = 0;
};
struct ClassAB
: public ClassA<InterfaceB>
{
void methodB() {}
};
int main()
{
InterfaceB* test = new ClassAB();
test->methodA();
}
So, we are having exactly one parent class.
But it looks more ugly when there is more than one "shared" class (InterfaceA is "shared", because it is on top of "dreaded diamond", see here https://isocpp.org/wiki/faq/multiple-inheritance as posted by Laura). See example (what will be, if ClassA implements interfaceC too):
struct InterfaceC
{
virtual void methodC() = 0;
};
struct InterfaceD : public InterfaceC
{
virtual void methodD() = 0;
};
template<class IA, class IC>
struct ClassA
: public IA //IA is expected to extend InterfaceA
, public IC //IC is expected to extend InterfaceC
{
void methodA() { 5+1;}
void methodC() { 1+2; }
};
struct InterfaceB : public InterfaceA
{
virtual void methodB() = 0;
};
struct ClassAB
: public ClassA<InterfaceB, InterfaceC> //we had to modify existing ClassAB!
{
void methodB() {}
};
struct ClassBD //new class, which needs ClassA to implement InterfaceD partially
: public ClassA<InterfaceB, InterfaceD>
{
void methodB() {}
void methodD() {}
};
The bad thing, that you needed to modify existing ClassAB. But you can write:
template<class IA, class IC = interfaceC>
struct ClassA
Then ClassAB stays unchanged:
struct ClassAB
: public ClassA<InterfaceB>
And you have default implementation for template parameter IC.
Which way to use is for you to decide. I prefer template, when it is simple to understand. It is quite difficult to get into habit, that B::incrementAndPrint() and C::incrementAndPrint() will print different values (not your example), see this:
class A
{
public:
void incrementAndPrint() { cout<<"A have "<<n<<endl; ++n; }
A() : n(0) {}
private:
int n;
};
class B
: public virtual A
{};
class C
: public virtual A
{};
class D
: public B
: public C
{
public:
void printContents()
{
B::incrementAndPrint();
C::incrementAndPrint();
}
};
int main()
{
D d;
d.printContents();
}
And the output:
A have 0
A have 1
This problem exists because C++ doesn't really have interfaces, only pure virtual classes with multiple inheritance. The compiler doesn't know where to find the implementation of methodA() because it is implemented by a different base class of ClassAB. You can get around this by implementing methodA() in ClassAB() to call the base implementation:
class ClassAB : public ClassA, public InterfaceB
{
void methodA()
{
ClassA::methodA();
}
void methodB();
}
You have a dreaded diamond here.
InterfaceB and ClassA must virtually inherit from InterfaceA
Otherwise you ClassAB has two copies of MethodA one of which is still pure virtual. You should not be able to instantiate this class. And even if you were - compiler would not be able to decide which MethodA to call.