Virtual multiple interface - c++

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.

Related

Inheritance with interfaces

I'm currently trying to wrap my head around the basics of C++ inheritance. Consider the following piece of code:
// Interfaces
class InterfaceBase
{
public:
virtual void SomeMethod() = 0;
};
class InterfaceInherited : public InterfaceBase
{
};
// Classes
class ClassBase : public InterfaceBase
{
public:
virtual void SomeMethod()
{
}
};
class ClassInherited : public ClassBase, public InterfaceInherited
{
};
int main()
{
ClassBase myBase; // OK
ClassInherited myInherited; // Error on this line
return 0;
}
Here I have two interfaces with an inheritance relationship. The same goes for the two classes which implement the interfaces.
This gives me the following compiler error:
C2259 'ClassInherited': cannot instantiate abstract class
It seems that the class ClassInherited does not inherit the implementation of SomeMethod from ClassBase. Thus it is abstract and cannot be instantiated.
How would I need to modify this simple example in order to let ClassInherited inherit all the implemented methods from ClassBase?
You are encountering a diamond problem.
The solution is to use virtual inheritance (Live), to ensure that only one copy of base class members are inherited by grand-childs:
// Interfaces
class InterfaceBase
{
public:
virtual void SomeMethod() = 0;
};
class InterfaceInherited : virtual public InterfaceBase
{
};
// Classes
class ClassBase : virtual public InterfaceBase
{
public:
virtual void SomeMethod()
{
}
};
class ClassInherited : public ClassBase, public InterfaceInherited
{
};
int main()
{
ClassBase myBase; // OK
ClassInherited myInherited; // OK
return 0;
}

Multiple inheritence with default implementation not working - forced to always override default implementation

What I want to do
I want to have a base interface and a lot of sub interface extenting this base interface
I want a default implementation of the default interface
I want that all my sub interface implementations extend the default implementation and only override those methods they want
I have defined following public interfaces - those are needed this way for the SDK I develop plugins for
// the base interface
class DYNAMIC_ATTRIBUTE IMasterProfile : public IVWUnknown
{
public:
virtual Uint16 VCOM_CALLTYPE GetNodeVersion() = 0;
// ...
}
// one of many sub interfaces extending the default one
class DYNAMIC_ATTRIBUTE ISomeProfile : public IMasterProfile
{
public:
virtual void VCOM_CALLTYPE SwapData() = 0;
};
My implementation looks like following:
class DYNAMIC_ATTRIBUTE MasterProfile : public virtual IMasterProfile
{
public:
Uint16 VCOM_CALLTYPE GetNodeVersion() override { return 0; };
// ...
}
class DYNAMIC_ATTRIBUTE SomeProfile : public MasterProfile, public virtual ISomeProfile
{
public:
void VCOM_CALLTYPE SwapData() override { }
}
Problems:
The compiler complains that SomeProfile is abstract and has not implemented GetNodeVersion function. How can I solve this? SomeProfile is extenting MasterProfile and this class is implementing the GetNodeVersion function...
EDIT: Possible solution
I can move the IMasterProfile default implementation into the header and everything works (additionally I remove the virtual inheritance). I am curious if this can be solved without moving the default implemention into the header...
The problem is with ambiguity. You must implement GetNodeVersion in ISomeProfile. Otherwise SomeProfile::ISomeProfile::GetNodeVersion is not defined and it's abstract.
Consider this code:
class IMasterProfile
{
public:
virtual int GetNodeVersion() = 0;
};
class ISomeProfile : public IMasterProfile
{
public:
virtual void SwapData() = 0;
int GetNodeVersion() override { return 2; };
};
class MasterProfile : virtual IMasterProfile
{
public:
int GetNodeVersion() override { return 3; };
// ...
};
class SomeProfile : public MasterProfile, public virtual ISomeProfile
{
public:
SomeProfile(){ std::cout<<ISomeProfile::GetNodeVersion();}
void print()
{
std::cout<<GetNodeVersion(); // ERROR: Call to the "GetNodeVersion" is ambiguous
std::cout<<MasterProfile::GetNodeVersion(); // Call to the GetNodeVersion from MasterProfile
std::cout<<ISomeProfile::GetNodeVersion(); // Call to the GetNodeVersion from ISomeProfile, without implementing it's virtual method
}
void SwapData() override { }
};
So the problem is line, when you want use in SomeProfile:
std::cout<<ISomeProfile::GetNodeVersion(); // Call to the GetNodeVersion from ISomeProfile, without implementing it's virtual method
Without implementation you can't do it, a definition is needed.

use virtual method of base class C++ in child of child class

I've created a class named 'Device' which get inherited by multiple devices (for example, RFDevice, AccelleroDevice)
The Device class inherited a Thread class. This Threadclass includes a Pure virtual function named run. Is it possible to accesss this pure virtual function in RFDevice or AcelleroDevice.
So,
ThreadClass->DeviceClass->RFDeviceClass.
I've tried to add
' virtual void run(void) = 0' also in the device class but this wont work.
Greets,
Only if the virtual function is not private. If it is, then you cannot call it and are not supposed to, either:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
private:
virtual void run() = 0;
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
public:
void f()
{
run(); // compiler error
}
};
If it is protected or public, then it will work, provided there is an implementation of the function somewhere down the class hierarchy. But with the exception of the destructor, virtual functions should rarely be public or protected in C++:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
protected:
virtual void run() = 0; // non-private virtual, strange
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
protected:
virtual void run()
{
}
public:
void f()
{
run(); // works
}
};
Of course, this does not technically call the base function. And that's a good thing; you'd end up with a pure virtual function call otherwise, and your program would crash.
Perhaps what you need to do is to just implement the private virtual function. That would be the preferred class design:
class ThreadClass
{
public:
virtual ~ThreadClass() {}
void execute()
{
run();
}
private:
virtual void run() = 0;
};
class Device : public ThreadClass
{
};
class RFDevice : public Device
{
private:
virtual void run()
{
}
};
int main()
{
RFDevice d;
d.execute();
}
If you are not just maintaining a legacy code base, you should probably get rid of your thread class and use C++11 multi-threading.

How to properly extend interface?

I have interface based on another:
class IDrawable {
public:
virtual ~IDrawable();
};
class IExtendedDrawable: public IDrawable {
public:
virtual ~IExtendedDrawable();
};
class DrawableImplementation: public IDrawable {
public:
virtual ~DrawableImplementation();
};
class ExtendedDrawableImplementation:
public DrawableImplementation, public IExtendedDrawable
{
public:
virtual ~ExtendedDrawableImplementation();
};
Then ExtendedDrawableImplementation = DrawableImplementation (+IDrawable) + IExtendedDrawable (+IDrawable)
Is it right to have IDrawable twice in same class?
I'll give the benefit of the doubt that you DO indeed need/want multiple inheritance. I see it as good in only limited situations, and interfaces is one of them (even Java allows this).
As said above, use virtual inheritance and be sure to only use pure virtual methods in the interface classes.
class IDrawable {
public:
virtual ~IDrawable();
virtual void doSomething() = 0;
};
class IExtendedDrawable: virtual public IDrawable {
public:
virtual ~IExtendedDrawable();
virtual void doSomethingElse() = 0;
};
class DrawableImplementation: virtual public IDrawable {
public:
virtual ~DrawableImplementation();
virtual void doSomething() {/*code here*/}
};
class ExtendedDrawableImplementation:
public DrawableImplementation, public IExtendedDrawable
{
public:
virtual ~ExtendedDrawableImplementation();
virtual void doSomething() {/*code here*/}
virtual void doSomethingElse() {/*code here*/}
};
It largely depends on the logic inside the classes is, but IMO you're better off using composition instead:
class ExtendedDrawableImplementation : public IExtendedDrawable
{
IDrawable* drawableImplementation; //points to a DrawableImplementation
public:
virtual ~ExtendedDrawableImplementation();
};
Multiple inheritance is rarely the answer.
Just derive ExtendedDrawableImplementation from IExtendedDrawable. That way it will have both interfaces anyway. I don't see why you would want to derive from both here.
I'm not C++ programmer, but from what I remember, it's correct. You don't have IDrawable twice, but you have multiple path to it. See http://en.wikipedia.org/wiki/Diamond_problem#The_diamond_problem

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.