How to delegate to implementing class - c++

I have an abstract base class Node, which is derived from an abstract Interface class IObservable.
There is a several classes implementing the abstract IObservable: SingleObservable and MultiObservable
I want to create a class ObservableNode, derived from the base Node class and specify on its declaration which class to use for the implementation of the IObservable interface.
I've added using ... statements for every pure virtual method in IObservable, referring to the methods in the implementation classes but I still get errors saying that ObservableNode is an abstract class, missing the implementation of notifyObservers(IObject*).
If I add the parameter IObject* to the using statement I get an "expected ';' before '(' token" error
How can I solve this?
class IObservable {
public:
virtual ~IObservable() {};
virtual void notifyObservers(IObject*) = 0;
};
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
//some implementaiton
};
};
class MultiObservable: public IObservable {
public:
virtual ~MultiObservable() {};
void notifyObservers(IObject*) override {
//some other implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
};
class ObservableNode: public Node, public SingleObservable {
public:
virtual ~ObservableNode() {};
using SingleObservable::notifyObservers;
// using SingleObservable::notifyObservers(IObject*); // expected ';' before '(' token error
};
Node* node = new ObservableNode() // instantiating abstract class error, missing notifyObservers(IObject*) implementation

Your problem seems to be that you inherit Node which is still abstract, and also causes to introduce the good old multimple inheritance vicious diamond problem. When I change your code like this, the error disappears:
class Node: public IObservable {
public:
virtual ~Node() {};
// ** Added an implementation here **
void notifyObservers(IObject*) override {
//some other implementaiton
};
};
class ObservableNode: public virtual Node, public virtual SingleObservable {
// ^^^^^^^ ^^^^^^^
public:
virtual ~ObservableNode() {};
using SingleObservable::notifyObservers;
};
int main() {
Node* node = new ObservableNode();
}
See it live on coliru.

#πάντα ῥεῖ's answer describe one workaround, but possible this is not what OP is after here. Also, as my comment describe under the answer, the approach in the answer might give unexpected results e.g. when invoking node->notifyObservers(obj):
Note that in this particular example, Node* node = new
ObservableNode(); will mean node->notifyObservers(obj) will invoke
Node::notifyObservers(IObject*) and not
SingleObservable::notifyObservers(IObject*), which might be
unexpected, considering we instantiate an ObservableNode object
which specifies using SingleObservable::notifyObservers;.
In OP's original code, we are suffering from multiple inheritance ambiguity, as we are not using virtual inheritance when Node and SingleObservable (and MultiObservable) derives from IObservable:
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
//some implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
};
Meaning our the object's memory layout, w.r.t. inheritance, of ObservableNode to looks like the following
IObservable IObservable
| |
Node SingleObservable
\ /
ObservableNode
whereas, in this context, we are likely to want an object's memory layout looking as follows
IObservable
/ \
Node SingleObservable
\ /
ObservableNode
If we were to correct this, Node can stay abstract, and a call to node->notifyObservers(obj) with node as OP's example will result in invocation of SingleObservable::notifyObservers, as might have been expected.
class Node: public virtual IObservable {
// ↑↑↑↑↑↑↑
public:
virtual ~Node() {};
};
class SingleObservable: public virtual IObservable {
// ↑↑↑↑↑↑↑
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "SingleObservable::notifyObservers";
};
};
struct DummyObj : public IObject {};
int main() {
Node* node = new ObservableNode();
DummyObj obj;
node->notifyObservers(obj); // SingleObservable::notifyObservers
}
Note that we not need virtual inheritance for when ObservableNode derives from Node and SingleObservable.
Finally, if we'd want Node be non-abstract (specifically, to provide an override of void notifyObservers(IObject*)), then ObservableNode must provide it's own (final) override of it, as we will otherwise inherit two final overrides of it in ObservableNode (one from Node and one from SingleObservable). In this case, ObservableNode could simply define its own override which explicitly calls the base class of choice, e.g.
class Node: public virtual IObservable {
public:
virtual ~Node() {};
void notifyObservers(IObject*) override {
std::cout << "Node::notifyObservers";
};
};
class SingleObservable: public virtual IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "SingleObservable::notifyObservers";
};
};
class ObservableNode: public Node, public SingleObservable {
public:
virtual ~ObservableNode() {};
// Non-ambiguous final override in ObservableNode.
// We could use `override` specifier here, but we might as well
// use `final`, if we are not expecting something to derive from ObservableNode.
void notifyObservers(IObject* obj) final {
SingleObservable::notifyObservers(obj);
};
};
struct DummyObj : public IObject {};
int main() {
Node* node = new ObservableNode();
DummyObj obj;
node->notifyObservers(obj); // SingleObservable::notifyObservers
}
See ISO C++ FAQ - Inheritance — Multiple and Virtual Inheritance for details on the diamond inheritance structure and virtual inheritance.

Thanks for all the suggestions! Implementing those caused a lot of other problems with other classes already using the Observable implementations, so I opted to solve it in a different manner, by including an implementation instance and delegating all methods to that one
class IObject {
public:
virtual ~IObject() {};
};
class IObservable {
public:
virtual ~IObservable() {};
virtual void notifyObservers(IObject*) = 0;
};
class SingleObservable: public IObservable {
public:
virtual ~SingleObservable() {};
void notifyObservers(IObject*) override {
std::cout << "Single\n";
//some implementaiton
};
};
class MultiObservable: public IObservable {
public:
virtual ~MultiObservable() {};
void notifyObservers(IObject*) override {
std::cout << "Multi\n";
//some other implementaiton
};
};
class Node: public IObservable {
public:
virtual ~Node() {};
// void notifyObservers(IObject*) override { };
};
class SingleObservableNode: public Node {
public:
SingleObservableNode() {};
virtual ~SingleObservableNode() {
delete obs;
};
void notifyObservers(IObject* obj) override {
obs->notifyObservers(obj);
}
private:
IObservable* obs = new SingleObservable();
};
class MultiObservableNode: public Node {
public:
MultiObservableNode() {};
virtual ~MultiObservableNode() {
delete obs;
};
void notifyObservers(IObject* obj) override {
obs->notifyObservers(obj);
}
private:
IObservable* obs = new MultiObservable();
};
Node* node1 = new SingleObservableNode();
Node* node2 = new MultiObservableNode();
int main()
{
node1->notifyObservers(nullptr); // "Single"
node2->notifyObservers(nullptr); // "Multi"
return 0;
}

Related

Defining a virtual method inherited more than once

I've been trying to find an answer to this question but I couldn't (I don't even know how to properly formulate this) so I decided to write my first post ever on StackOverflow =).
The context is the following:
I have this parent class:
class Parent
{
public:
Parent(){};
void foo(void)
{
//Do some common things
bar();
//Do some more common things
};
protected:
virtual void bar(void) = 0;
};
And I want to create an indefinite amount of derived Childs:
class Child1 : public Parent
{
public:
Child1() : Parent(), child1Variable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t child1Variable;
};
class Child2 : public Parent
{
public:
Child2() : Parent(), child2Variable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t child2Variable;
};
.
.
.
class ChildN : public Parent
{
public:
ChildN() : Parent(), childNVariable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t childNVariable;
};
The reason being mainly not repeating the code in Parent's foo()
Then I would like to create my final instantiable classes as, for instance:
class ExampleFinal : public Child1, public Child3, public Child27
{
//How to define Child1::bar(), Child3::bar() and Child27::bar() ??
private:
void bar(void); //????
};
So the questions are:
How can I define the method for (abusing notation) ExampleFinal::Child1::bar, ExampleFinal::Child3::bar, ...
Am I so stuck on this that I'm overlooking a much simpler solution?
The final goal is being able to do something like:
ExampleFinal test;
test.Child1::foo(); //should end up on "ExampleFinal::Child1::bar"
test.Child3::foo(); //should end up on "ExampleFinal::Child3::bar"
Thanks!
Implementing ExampleFinal::bar() (side-note: bar(void) is a C-ism which has no use in C++) will override all of the bars you have declared at once. If you want to have different versions, you'll need to interpose another layer of classes:
struct GrandChild1 : Child1 {
void bar() override { /*...*/ }
};
// And so on...
struct ExampleFinal : GrandChild1, GrandChild3, GrandChild27 {
// Nothing needed here.
};
Then the behaviour you described will work. Be aware, though, that your inheritance graph means that an ExampleFinal has one Parent subobject per Child. This is not an issue in itself but might not model what you want -- maybe you need virtual inheritance here, but beware of the rabbit hole.
If you want to keep the overrides for all ChildN::bars inside ExampleFinal, you can add tag-dispatching to discern them, at the cost of one more virtual call:
struct Parent {
void foo() {
bar();
};
protected:
template <class Child>
struct tag { };
virtual void bar() = 0;
};
struct Child1 : Parent {
protected:
virtual void bar(tag<Child1>) = 0;
void bar() final override {
return bar(tag<Child1>{});
}
int child1Var;
};
struct Child2 : Parent {
protected:
virtual void bar(tag<Child2>) = 0;
void bar() final override {
return bar(tag<Child2>{});
}
int child2Var;
};
struct ExampleFinal : Child1, Child2 {
protected:
using Parent::tag;
void bar(tag<Child1>) final override {
std::cout << "Child1::bar\n";
}
void bar(tag<Child2>) final override {
std::cout << "Child2::bar\n";
}
};
Note that the bar() to bar(tag<ChildN>) bridge can easily be hidden behind a macro. If you want to avoid the cost of the second virtual call, a CRTP can also be applied here.

Calling the right free function from a base pointer/reference

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);
}

Inheritance and pointers to protected members

I'm currently creating a basic UI system for a game I'm writing. It's organized as a tree of nodes. I'm trying to write it so that only the root node can call the update method on other nodes. I thought I understood C++ inheritance but it's once again laughing at my incompetence. I've tried to create a bare-bones example below:
class Base
{
public:
virtual ~Base() { }
protected:
virtual void update_internal() = 0;
};
class Node_A : public Base
{
protected:
virtual void update_internal() { std::cout << "Update Node A" << std::endl; }
};
class Node_B : public Base
{
protected:
virtual void update_internal() { std::cout << "Update Node B" << std::endl; }
};
class Root : public Base
{
public:
void add_node (Base* node) { m_nodes.push_back(node); }
void update()
{
for (auto& node : m_nodes)
{
node->update_internal();
}
}
protected:
std::vector<Base*> m_nodes;
virtual void update_internal() { }
};
int main()
{
Node_A alpha_node;
Node_B beta_node;
Root root_node;
root_node.add_node(&alpha_node);
root_node.add_node(&beta_node);
root_node.update();
}
When I try to compile this GCC gives me the error:
error: 'virtual void Base::update_internal()' is protected
All of the nodes including root inherit the update_internal() method from Base, I don't understand why it matters that it is protected. I thought it was only private members and methods that derived classes couldn't access.
You can only call a protected/private function of a base class only from an instance of the derived class (unless of course you use friends). So the derived class can only access the private/protected members of its base part, not of some other base. In your case, you call it via a reference to a Base* in
for(auto& node : m_nodes)
node->update_internal();
so the compiler complains.
Just befriend Base and Root;
class Base
{
friend class Root; // <- yes,this
public:
virtual ~Base() { }
protected:
virtual void update_internal() = 0;
};
This is a stock example for the Template Method pattern.
The public method of the Root class exposes, what's needed to be implemented internally.
class Base
{
protected:
virtual void update_internal() = 0;
static void DoUpdate( Base *node )
{
node->update_internal();
}
};
class Root : public Base
{
public:
void update()
{
for (auto node : m_nodes)
{
Base::DoUpdate( node );
}
}
protected:
virtual void update_internal() override {}
std::vector<Base*> m_nodes;
};

Using CRTP with virtual inheritance

I have a hierarchy of nodes, where "diamond" can occurred.
Every node must be clonable but I don't want to write clone method to every node. So I use CRTP.
class Node
{
public:
Node(){}
Node(Fill*) { }
virtual ~Node() {}
virtual Node * clone() const = 0;
virtual void id() { std::cout << "Node\n"; }
};
//====================================================================
template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:
NodeWrap() { }
NodeWrap(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
works as follows:
class NodeA : public NodeWrap<Node, NodeA>
{
public:
typedef NodeWrap<Node, NodeA> BaseClass;
NodeA() { }
NodeA(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeA\n"; }
};
First question:
There is know BUG in VS when "covariance is used with virtual inheritance".
Is there a way to overcome the bug, and still have covariant types is clone method?
I changed return type to be Node instead of Base. I can live with that, but I would like to have Base as return type
Second question:
Problem occurred when multiple inheritance comes to play. I created new wrapper, which inherits virtually
template <typename Base, typename Derived>
class NodeWrapVirtual : public virtual Base
{
public:
NodeWrapVirtual() { }
NodeWrapVirtual(Fill * arg1) : Base(arg1) { }
virtual Node *clone() const
{
return new Derived(static_cast<Derived const &>(*this));
}
};
and now building diamond structure:
class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
typedef NodeWrapVirtual<Node, NodeB> BaseClass;
NodeB() { }
NodeB(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeB\n"; }
};
//====================================================================
class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
typedef NodeWrapVirtual<Node, NodeC> BaseClass;
using BaseClass::clone;
NodeC() { }
NodeC(Fill * f) : BaseClass(f) { }
virtual void id() { std::cout << "NodeC\n"; }
};
and problematic diamond node:
class NodeD : public NodeWrap<NodeB, NodeD>,
public NodeWrap<NodeC, NodeD>
{
public:
typedef NodeWrap<NodeB, NodeD> BaseClassB;
typedef NodeWrap<NodeC, NodeD> BaseClassC;
NodeD() { }
NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }
using BaseClassB::clone; // (1)
virtual NodeD *clone() const { return new NodeD(*this); } // (2)
virtual void id() { std::cout << "NodeD\n"; }
};
where are 2 lines I am curious about. (line (1) and (2))
If both lines are removed, there is oblivious compile error, because there is ambiguous clone method (from every parent). Since I don't use covariant return types, there should work clone method form each parent, so i use line (1) but it doesn't work. Still ambiguous.
So I use line (2) and it works.
Is there a nice way, to avoid writing line (2)?
HERE is full working example on ideone.
First you should be very carefull to use virtual inheritance with members inside the virtual base (look at https://stackoverflow.com/a/1193516/1918154, "Effective C++", item 20: "Avoid data members in public interfaces" and http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8). Your node gets an pointer to a fill which is not used, but it looks like you need it somewhere.
Your problem can be solved when you move the inhertance relationship (public virtual and public) in the base class for your NodeWrap.
template <typename Base>
class InheritVirtual
: public virtual Base
{};
template <typename... Bases>
class InheritBases
: public Bases...
{
virtual Node* clone() const = 0;
virtual void id() const = 0;
};
class NodeB : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeC : public NodeWrap<InheritVirtual<Node>, NodeB>
{
//...
};
class NodeD : public NodeWrap<InheritBases<NodeB,NodeC>, NodeD>
{
//...
};
Running Example.
The pure virtual methods in InheritBases are needed because the so called domination rule (Dominance in virtual inheritance).
The problem to be solved is a way to transfer paramters to the right constructor in case of multiple bases. Unlike Node (wich is a virtual base) it is ok to let NodeB and NodeC have member variables and non trivial constructors.
Each virtual function must have a unique final overrider in each derived class. This has nothing to do with name lookup (the requirement is for the functions, not for their names), thus using is irrelevant.
Use a multi-base-classed node class template:
template <class Derived, class Base1, class Base2>
class node2 : // etc
// or use a variadic template if you have more than two bases
As for covariant returns, they are strictly unnecessary, if convenient. You can always split each virtual function into a private virtual and a public non-virtual. This comes handy if you want to return covariant smart pointers, which is not supported by the regular covariant return machinery at all.

Interface Inheritance in C++

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.