I came from JVM world and I try to implement something in c++.
I have an interface:
class MyInterface
{
public:
virtual void my_method(std::string i) = 0;
virtual void my_method(int i) = 0;
};
And I would like to have two subclasses A and B:
class AClass: public MyInterface
{
public:
void my_method(std::string i); // And implement only that method in .c file
}
And class B:
public BClass: public MyInterface
{
public:
void my_method(int i); // And implement only that method in .c file
}
But I got errors. (I cannot paste logs because I have production code only and the code above is only the scaffolding of the real problem).
Is there any pattern to avoid overriding some virtual methods?
Is there any pattern to avoid overriding some virtual methods?
I don't think there is any pattern for that. You just have to make sure that all virtual member functions are implemented in the most derived class or one of its parent classes.
A trivial implementation is not too hard for the functions you have.
class AClass: public MyInterface
{
public:
void my_method(std::string i); // And implement only that method in .c file
void my_method(int i) {} // That's all you need
};
Your child classes selectively override parent methods.
You need something like this :
class MyInterface // Consider a different name
{
public:
virtual void my_method(std::string i) {
// Business Logic . Let child 1 override this
}
virtual void my_method(int i) {
// Business Logic . Let child 2 override this
}
};
In short you can't have an abstract base here.
Related
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();
}
};
Suppose that I have a heirarchy of several classes:
class A {
public:
virtual void DoStuff() = 0;
};
class B : public A {
public:
// Does some work
void DoStuff() override;
};
class C : public B {
public:
// Calls B::DoStuff and does other work
void DoStuff() override;
};
It can naively be implemented:
void Derived::DoStuff() {
Base::DoStuff();
...
}
This implementation has a serious problem, I believe: one always has to remember to call base implementation when overrides.
Alternative:
class A {
public:
void DoStuff() {
for (auto& func: callbacks_) {
func(this);
}
}
virtual ~A() = default;
protected:
template <class T>
void AddDoStuff(T&& func) {
callbacks_.emplace_back(std::forward<T>(func));
}
private:
template <class... Args>
using CallbackHolder = std::vector<std::function<void(Args...)>>;
CallbackHolder<A*> callbacks_;
};
Usage:
class Derived : public Base {
public:
Derived() {
AddDoStuff([](A* this_ptr){
static_cast<Derived*>(this_ptr)->DoStuffImpl();
});
}
private:
void DoStuffImpl();
};
However, I believe that it has a good amount of overhead when actually calling DoStuff(), as compared to the first implementation. In the use cases which I saw, possibly long costruction of objects is not a problem (one might also try to implement something like "short vector optimization" if he wants).
Also, I believe that 3 definitions for each DoStuff method is a little too much boilerplate.
I know that it can be very effectively solved by using inheritance pattern simular to CRTP, and one can hide the template-based solution behind interface class (A in the example), but I keep wondering -- shouldn't there be an easier solution?
I'm interested in a good implementation of call DERIVED implementation FROM BASE, if and only if derived class exists and it has an overriding method for long inheritance chains (or something equivalent).
Thanks!
Edit:
I am aware of an idea described in #Jarod42's answer, and I don't find it appropriate because I believe that it is ugly for long inheritance chains -- one has to use a different method name for each level of hierarchy.
You might change your class B to something like:
class A {
public:
virtual ~A() = default;
virtual void DoStuff() = 0;
};
class B : public A {
public:
void DoStuff() final { /*..*/ DoExtraStuff(); }
virtual void DoExtraStuff() {}
};
class C : public B {
public:
void DoExtraStuff() override;
};
I am not sure if I understood correctly but this seems to be addressed pretty good by the "Make public interface non-virtual, virtualize private functions instead" advice.
I think it's orignated in the Open-Closed principle. The technique is as-follows:
#include <iostream>
class B {
public:
void f() {
before_f();
f_();
};
private:
void before_f() {
std::cout << "will always be before f";
}
virtual void f_() = 0;
};
class D : public B{
private:
void f_() override {
std::cout << "derived stuff\n";
}
};
int main() {
D d;
d.f();
return 0;
}
You essentially deprive descendant class of overriding public interface, only customize exposed parts. The base class B strictly enforces that required method is called before actual implementation in derived might want to do. As a bonus you don't have to remember to call base class.
Of course you could make f virtual as well and let D decide.
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.
I am looking at refactoring a lot of code and have discussed a bit in relations to the best way of handling inheritance. Given the following three classes
class Listener_Interface {
public:
virtual void message(data& data);
}
class Timing_Interface {
public:
virtual void timerEvent(data& data);
}
class Action_Interface {
public:
virtual void action(data& data);
}
There is a need for a class to implement all these plus provide a some extra specifik methods.
Should I inherit like this:
class NewClass_Interface :
public Listener_Interface,
public Timing_Interface,
public Action_Interface {
public:
virtual void newMethod();
}
class NewClass : NewClass_Interface {
....
}
or
class NewClass_Interface {
public:
virtual void newMethod();
}
class NewClass :
public NewClass_Interface
public Listener_Interface,
public Timing_Interface,
public Action_Interface {
....
}
To me the previous seems more correct and easier to test etc. But for some reason all the classes and code looks lite the latter.
It depends on your logic. Sometimes you might want your NewClass_Interface to not necessarily have a relation with Listener, Timing and Action. But since it doesn't look like the case here, I agree with you. The better you constraint the use of your interfaces, the more reliable your code will be.
So I would go with this:
class Listener_Interface {
public:
virtual void message(data& data) = 0;
}
class Timing_Interface {
public:
virtual void timerEvent(data& data) = 0;
}
class Action_Interface {
public:
virtual void action(data& data) = 0;
}
(Observe how I make your methods pure virtual in order to make your classes real interfaces)
class NewClass_Interface :
public Listener_Interface,
public Timing_Interface,
public Action_Interface
{
public:
virtual void newMethod() = 0;
}
class NewClass : NewClass_Interface {
....
}
This way you'll have better control on what is going on.
Also, I would advise you of using the most common standard for Interfaces naming: IListener, ITiming, IAction and INewClass.
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