I have a class that does something similar to:
class B{
void x(){
statement-block1;
statement-block2;
statement-block3;
statement-block4;
}
void y(){
statement-block5;
statement-block6;
statement-block7;
statement-block8;
}
}
I need to add a new class that does this:
class C{
void x(){
statement-block1;
statement-block200;
statement-block3;
statement-block4;
}
void y(){
statement-block5;
statement-block6;
statement-block700;
statement-block8;
}
}
I was considering combining the reusable logic this way:
class A{
void x(){
statement-block1;
statement-block2;
u();
statement-block4;
}
void y(){
statement-block5;
statement-block6;
v();
statement-block8;
}
virtual void u(){
default-message;
}
virtual void v(){
default-message;
}
}
class B : A{
void u(){
statement-block3;
}
void v(){
statement-block7;
}
}
class C : A{
void u(){
statement-block200;
}
void v(){
statement-block700;
}
}
Is there a better way to implement this, a different/better way of injecting sub-class-specific code, or is there a design pattern I can use? In the future, I might have to add more classes similar to B and C.
Thanks!
It depends what you are trying to achieve. If the statements block are likely to change in run time (dynamic) then use virtual pointer as you showed in your example, however if those are not dynamic, then pass a template parameter instead, in that way you don't pay for what you don't use (virtual pointer). i.e.
class B
{
public:
template <typename T>
void x(T f)
{
f();
}
};
void g(){ std::cout << "value" << std::endl;}
int main()
{
B b {};
b.x(g);
}
Your approach looks great. It applied KISS which is most often the best design pattern to use! You could do this
virtual void u(){
default-message;
}
virtual void v(){
u();
}
But that's up to you I guess
Another option is to combine all classes and use std function or a function pointer for that function call that changes.
Related
I have a dumb c++ design question. Is there a way for one class to have the same method names (hence, the same API) of the methods found in several classes?
My current situation is that I have a situation where I have classes
struct A
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
.... imagine possibly more
What I really want is another class that acts an interface for those of these functionalities. I might be misinterpreting as the facade design pattern for a simple interface that hides the complexity of instantiating classes above but still use their same interface.
struct C
{
void foo() { ... }
void boo() { ... }
void moo() { ... }
void goo() { ... }
};
For small number of methods shown above this is feasible by either declaring structs A and B or passing them in as parameters to struct C and call the methods of A and B in C but this is impracticable if A has 40 methods and B has 30 has methods. Redeclaring 70 methods with the same name in C to call the underlying methods of A and B seemed like a lot of redundancy for no reason if I could do better.
I thought of a second solutions of using a base class
struct base
{
void foo() { }
void boo() { }
void moo() { }
void goo() { }
};
struct A : public base
{
void foo() { std::cout << "A::foo" << std::endl;}
void boo() { std::cout << "A::boo" << std::endl;}
};
struct B : public base
{
void moo() { std::cout << "B::moo" << std::endl;}
void goo() { std::cout << "A::goo" << std::endl;}
};
To try and use a shared_ptr that has all the function definitions. e.g
std::shared_ptr<base> l_var;
l_var->foo();
l_var->boo();
l_var->moo();
l_var->goo();
That still doesn't quite give me what I want because half of the methods are defined in struct A while the other half is in struct B.
I was wondering if multiple inheritance would do the trick but in school I heard it's bad practice to do multiple inheritance (debugging is hard?)
Any thoughts or recommendations? Basically it's easier to manage struct A and B (and so on as it's own class for abstraction purposes). But would like the flexibility of somehow calling their methods in some wrapper where this complexity is hidden from the user.
I think that
Redeclaring 70 methods with the same name in C to call the underlying
methods of A and B
is the right path.
It is tempting to use multiple inheritance in cases like this to avoid writing pass-through code but I think that is generally a mistake. Prefer composition over inheritance.
I would question whether your user really wants to deal with one interface with 70 methods but if that's really what you want then I don't see why it is "impractical" to write the code in C:
class C {
A a;
B b;
public:
void foo() { return a.foo(); }
void boo() { return a.boo(); }
void moo() { return b.moo(); }
void goo() { return b.goo(); }
// ...
};
Live demo.
This has the advantage that you can easily change your mind in the future and replace A and B with something else without changing the interface of C.
You can hide the implementation of C further by using the PIMPL idiom or by splitting C into an abstract base class C and an implementation CImpl.
A Bridge Design Pattern will shine here. By decoupling abstraction from its implementation , many derived classes can used these implementations separately.
struct base {
protected:
struct impl;
unique_ptr<impl> _impl;
};
struct base::impl {
void foo() {}
void bar() {}
};
struct A :public base {
void foo() { _impl->foo(); }
};
struct B:public base {
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
};
Edited ( eg implementation)
#include <memory>
#include <iostream>
using namespace std;
struct base {
base();
protected:
struct impl;
unique_ptr<impl> _impl;
};
struct base::impl {
void foo() { cout << " foo\n"; }
void bar() { cout << " bar\n"; }
void moo() { cout << " moo\n"; }
void goo() { cout << " goo\n"; }
};
base::base():_impl(new impl()) {}
struct A :public base {
A():base() { }
void foo() { _impl->foo(); }
};
struct B:public base {
B() :base() { }
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
};
struct C :public base {
C() :base() { }
void foo() { _impl->foo(); }
void bar() { _impl->bar(); }
void moo() { _impl->moo(); }
void goo() { _impl->goo(); }
};
int main()
{
B b;
b.foo();
C c1;
c1.foo();
c1.bar();
c1.moo();
c1.goo();
return 0;
}
Use virtual multiple inheritance. The reason why
it's bad practice to do multiple inheritance
is because it directly will lead to ambiguous calls or redundant data, so you can use virtual inheritance to avoid it.
Learn how C++ implement iostream will help a lot, I thought.
I second Chris Drew's answer: not only multiple iharitance is bad, any inharitance is bad, compared to composition.
The purpose of the Fascade pattern is to hide complexity. As in, given your classes A and B with 40 and 30 methods, a Fascade would expose about 10 of them - those, needed by the user. Thus is avoided the problem of "if A has 40 methods and 30 has methods" then you have a big problem – n.m.
By the way, I love how you are using struct{} instead of class{public:}. This is quite controversial and the general consensus is it constitutes bad form, but stl does it and I do it.
Back to the question. If really all the 70 methods need to be exposed (!!), I would take a more pythonistic approach:
struct Iface
{
A _a;
B _b;
};
If you manage to make the fields const, things get even less bad. And for the third time - you are probably violating SRP with those large classes.
I'm writing plugins for an application through its C++ SDK. The mechanism is fairly simple. A plugin provides its functionality through predefined interfaces. This is done by having server classes inherit from one implementation class per interface, which contains either pure vitual functions or non-pure functions with default implementations.
This is very practical as SDK clients only have to override those methods that the plugin requires and/or provide an implementation for the (rare) ones with no default.
What has been bugging me is that everything is known at compile time. The virtual function tables and machinery associated with runtime polymorphism are here only for the sake of providing default implementations.
I'm attempting to remove this overhead while keeping the convenience.
As a (very contrived) example, say I have a couple of servers presenting a single interface (named Blah) consisting of only one method with no default implementation.
// SDK header
struct OldImpl_Blah {
virtual ~OldImpl_Blah() =default;
virtual int mult(int) =0;
};
// plugin source
class OldServer3 : public OldImpl_Blah {
public:
int mult(int i) override { return 3 * i; }
};
class OldServer5 : public OldImpl_Blah {
public:
int mult(int i) override { return 5 * i; }
};
For pure virtual functions, straight forward CRTP works just fine.
// SDK header
template <typename T>
struct NewImpl_Blah {
int mult(int i) { return static_cast<T*>(this)->mult(i); }
};
// plugin source
class NewServer3 : public NewImpl_Blah<NewServer3> {
public:
int mult(int i) { return 3 * i; }
};
class NewServer5 : public NewImpl_Blah<NewServer5> {
public:
int mult(int i) { return 5 * i; }
};
The problem is with non-pure virtual functions, i.e. when there is a default implementation for the method.
// SDK header
struct OldImpl_Blah {
virtual ~OldImpl_Blah() =default;
virtual int mult(int i) { return i; } // default
};
// plugin source
class OldServer3 : public OldImpl_Blah {
public:
int mult(int i) override { return 3 * i; }
};
class OldServer5 : public OldImpl_Blah {
public:
int mult(int i) override { return 5 * i; }
};
I tried to combine CRTP with some expression SFINAE trickery and failed.
I guess what I need is some kind of code dispatching where the base class would either provide a default implementation or forward its arguments to the implementation in the derived class, if it exists.
The problem seems to be that the dispatch should rely on information that is not yet available to the compiler in the base class.
A simple solution would be to just remove the virtual and override keywords in the code. But then the compiler wouldn't check that the function signatures match.
Is there some well known pattern for this situation? Is what I'm asking possible at all?
(Please use small words as my expertise with templates is a bit on the light side. Thanks.)
As always, Yet Another Level of Indirection is the solution. In this particular case, it's the well known technique of public non-virtual functions calling private or protected virtual functions. It have its own uses, independent of what is being discussed here, so check it out regardless. Normally it works like this:
struct OldImpl_Blah {
piblic:
virtual ~OldImpl_Blah() = default;
int mult(int i) { return mult_impl(i); }
protected:
virtual int mult_impl(int i) { return i; }
};
// plugin source
class OldServer3 : public OldImpl_Blah {
protected:
int mult_impl(int i) override { return 3 * i; }
};
With CRTP it's exactly the same:
template <class T>
struct OldImpl_Blah {
piblic:
virtual ~OldImpl_Blah() = default;
int mult(int i) { return static_cast<T*>(this)->mult_impl(i); }
protected:
virtual int mult_impl(int i) { return i; }
};
// plugin source
class OldServer3 : public OldImpl_Blah<OldServer3> {
protected:
int mult_impl(int i) override { return 3 * i; }
};
Disclaimer: CRTP is said to eliminate virtual call overhead by nit requiring functions to be virtual. I don't know if CRTP has any performance benefits when functions are kept virtual.
Consider using something like policy design:
struct DefaultMult {
int mult(int i) { return i; }
};
// SDK header
template <typename MultPolicy = DefaultMult>
struct NewImpl_Blah {
int mult(int i) { return multPolicy.mult(i); }
private:
MultPolicy multPolicy;
};
// plugin source
class NewServer3 {
public:
int mult(int i) { return 3 * i; }
};
class NewServer5 {
public:
int mult(int i) { return 5 * i; }
};
void client() {
NewImpl_Blah<NewServer5> myServer;
}
Also note that in theory using final keyword with override enables compilers to dispatch more optimally than vtable approach. I expect modern compilers to optimise if you use final keyword in your first implementation.
Some helpful refs:
mixin design
For more on policy based design you can watch video or read book / article by Andrei Alexandrescu
To be honest I'm not sure I'd use the following code, but I think it does what the OP is asking for.
This is a minimal, working example:
#include<iostream>
#include<utility>
template<class D>
struct B {
template <typename T>
struct hasFoo {
template<typename C>
static std::true_type check(decltype(&C::foo));
template<typename>
static std::false_type check(...);
static const bool value = decltype(check<T>(0))::value;
};
int foo() {
return B::foo<D>(0, this);
}
private:
template<class T>
static auto foo(int, B* p) -> typename std::enable_if<hasFoo<T>::value, int>::type {
std::cout << "D::foo" << std::endl;
return static_cast<T*>(p)->foo();
}
template<class T>
static auto foo(char, B*) -> typename std::enable_if<not hasFoo<T>::value, int>::type {
std::cout << "B::foo" << std::endl;
return 42;
}
};
struct A: B<A> { };
struct C: B<C> {
int foo() {
std::cout << "C::foo" << std::endl;
return 0;
}
};
int main() {
A a;
a.foo();
std::cout << "---" << std::endl;
B<A> *ba = new A;
ba->foo();
std::cout << "---" << std::endl;
C c;
c.foo();
std::cout << "---" << std::endl;
B<C> *bc = new C;
bc->foo();
}
If I did it right, there are no virtual methods, but the right implementation of foo is called, no matter if you are using a base class or a derived one.
Of course, it is designed around the CRTP idiom.
I know, the member detector class is far from being good.
Anyway, it's enough for the purpose of the question, so...
I believe, I understand what you are trying to do. If I am correct in my understanding, that can't be done.
Logically, you would want to have mult in Base to check if mult is present in the child struct - and if it does, call it, if it does not, provide some default implementation. The flaw here is that there always be mult in child class - because it will inherit implementation of checking mult from Base. Unavoidably.
The solution is to name function differently in the child class, and in the base check for presence of differently named function - and call it. This is a simple thing to do, let me know if you'd like the example. But of course, you will loose the beauty of override here.
A case where 'problem' should not be a problem in the title.
I want to implement a solver (class Solver) for a collection of problems (all children of class Problem), which more or less share the same set of methods. My current design is like this:
In solver.h:
template<class P>
class Solver{
public:
P* p;
Solver(P* problem) : p(problem) {}
void justDoIt(){
p->step1();
p->step2();
p->step3();
p->step4();
p->step5();
}
}
In main.cpp:
#include "solver.h"
class A {
public:
void step1() {}
void step2() {}
void step3() {}
void step4() {}
void step5() {}
};
class B: public A {
public:
void step2() {}
void step4() {}
};
class C: public A {
public:
void step3() {}
void step4() {}
void step5() {}
};
int main(){
B b;
C c;
Solver<B> sb(&b);
Solver<C> sc(&c);
sb.justDoIt();
sc.justDoIt();
return 0;
}
If I want to extend Solver for a new problem type, say C, and it
does nothing in step1();
does step2.5() between step2() and step3()
Now calling C c; Solver<C> sc(&c); c.justDoIt(), I need to modify A, B and Solver::justDoIt() first.
Is there a scalable to design the interface that adding new problem types (all childern of A) for Solver?
PS: The current codebase I am about to modify has 47 types of problems all using the same Solver class. Minimal change is preferred.
How can I do it better?
At least to me this design seems like a (pardon the technical jargon) mess.
Right now, Solver has intimate knowledge of the internals of Problem. Further, it appears there's no way for Solver to do its job without intimate knowledge of the internals of Problem either.
At least in my estimation, what you've called Solver::justDoIt() should really be Problem::operator(). If many of the Problems use step1() through step5() as you've shown in Solver, you can provide that implementation by default in Problem itself, then those that need to override that will provide their own implementations:
class Problem {
protected:
virtual void step1() {}
// ...
virtual void step5() {}
public:
virtual void operator()() {
step1();
step2();
step3();
step4();
step5();
}
};
class B : public Problem {
protected:
void step2() {}
void step4() {}
};
class C : public Problem {
protected:
virtual void step3() {}
virtual void step4() {}
virtual void step5() {}
};
Then the main looks something like this:
int main() {
B b;
C c;
b();
c();
}
Or, if you prefer shorter code:
int main() {
B()();
C()();
}
This creates a temporary object of each type, then invokes the operator() on that temporary object. I'm not particularly fond of it, but some people think it's great.
Virtual Functions:
The first option that should come into mind is to use virtual functions:
Redefine your Problem-class to contain a pure virtual function (that means: every child needs to reimplement it):
class Problem{
public:
virtual void allSteps()=0;
};
Redefine your Solver to call this special function:
class Solver{
public:
Problem* p;
Solver(Problem* prob):p(prob){}
void solve(){
p->allSteps();
}
};
And add an implementation in every child-class:
class MyProblem: public Problem{
public:
void step1(){
std::cout << "step1\n";
}
void step2(){
std::cout << "step1\n";
}
void stepx(int x){
std::cout << "step"<<x<<"\n";
}
void allSteps(){
step1();
step2();
stepx(3);
stepx(4);
}
};
And use your main-function as you did before:
int main() {
MyProblem myP;
Solver s(&myP);
s.solve();
return 0;
}
Try it here: http://ideone.com/NOZlI6
Function-Pointers/Objects
This is a slightly more complex solution, but depending on your needs (e.g. executing only a single step and then do something else) it might better fit your needs.
Whenever you see something like "foo1","foo2","foo3",... you should think of an array or a vector. And the same can be applied to your Problem:
First of all, redefine your "Problem" class to take an arbitrary amount of function pointers - or using c++, function objects:
class Problem{
public:
std::vector<std::function<void(void)>> functions;
};
Then all your Solver needs to do is to iterate over the function objects inside your Problems class:
class Solver{
public:
Problem* p;
Solver(Problem* prob):p(prob){}
void solve(){
for(auto func : p->functions)
func();
}
};
In order to register your classes functions properly, you need to remember that member-functions have an additional "hidden" parameter "this" that is a pointer to the class itself. But we can use std::bind to make a void(void) function out of any function we have. An alternative would be to use static functions, but since this should be easy to figure out, i will use the more complex way here:
class MyProblem: public Problem{
public:
void step1(){
std::cout << "step1\n";
}
void step2(){
std::cout << "step1\n";
}
void stepx(int x){
std::cout << "step"<<x<<"\n";
}
MyProblem(){
functions.push_back(std::bind(&MyProblem::step1,this));
functions.push_back(std::bind(&MyProblem::step2,this));
functions.push_back(std::bind(&MyProblem::stepx,this,3));
functions.push_back(std::bind(&MyProblem::stepx,this,4));
}
};
Your main-function will then be unaffected:
int main() {
MyProblem myP;
Solver s(&myP);
s.solve();
return 0;
}
Try it here: http://ideone.com/BmIYVa
I have this interface:
struct I
{
virtual void f(int) = 0;
virtual void f(float) = 0;
};
May I implemnt I using something similar to next class?
struct C : public I
{
template<typename T>
void f(T);
};
No, you can't do that. The template method overloads the original two methods (i.e. it's a different method with the same name). C still has two pure virtual functions.
As properly pointed out by NPE, you can't do this directly. However, you still can avoid code duplication by delegation:
struct C : public I
{
void f(int x) { f_internal(x); }
void f(float x) { f_internal(x); }
private:
template<typename T>
void f_internal(T x) { do stuff with x; }
};
#include<iostream>
using namespace std;
class Abs
{
public:
virtual void hi()=0;
};
class B:public Abs
{
public:
void hi() {cout<<"B Hi"<<endl;}
void bye() {cout<<"B Bye"<<endl;}
};
class C:public Abs
{
public:
void hi() {cout<<"C Hi"<<endl;}
void sayonara() {cout<<"C Sayonara"<<endl;}
};
int main()
{
Abs *bb=new B;
bb->bye();
Abs *cc=new C;
cc->sayonara();
}//main
The compiler says
test2.cpp: In function ‘int main()’:
test2.cpp:26: error: ‘class Abs’ has no member named ‘bye’
test2.cpp:28: error: ‘class Abs’ has no member named ‘sayonara’
Because of this problem, I'll have to add functions to the Abs class each time I create a new derived class which inherits from it (Upcasting is compulsory for me to do. The program I'm planning requires it to be so). I don't want to touch the base class once it's created.
Doesn't this problem violate the principle that once you make a base class, you won't have to modify it ever. Any way to resolve this problem?
p.s: I've seen the factory design pattern and the prototype design patterns, but both of them can't seem to be able to solve it.
This is defeating the purpose of inheritance and abstract interfaces. bye and sayonara both do the same thing (saying goodbye), only in different languages. This means you should have an abstract say_goodbye method that gets overridden for subclasses. I suppose this is a simplified example, so maybe you could describe your actual scenario so we can provide more specific help.
Edit If you want to create a copy of the derived class through an abstract interface, check out this question. If you want to explicitly access the different attributes of your subclasses, you should be asking your self if subclassing es even appropriate here, since your classes don't seem to have much in common.
Well, i'm not sure to understand exactly what you want (and why you want it that way) but:
int main()
{
Abs *bb=new B;
static_cast<B*>(bb)->bye();
Abs *cc=new C;
static_cast<C*>(cc)->sayonara();
}//main
Will work.
You just have to be sure that bb is really a B* before you static_cast.
You may also use dynamic_cast which will return a null pointer if bb is not of the correct type.
int main()
{
B *bb = new B;
bb->bye();
C *cc=new C;
cc->sayonara();
}//main
This way modifications in the base class are no longer needed :)
Dynamic casting is a sensible option. If you're religious about dynamic casts, you can use the visitor design pattern:
struct Abs;
struct B;
struct C;
struct Visitor
{
virtual ~Visitor() {}
// Provide sensible default actions
virtual void visit(Abs&) const { throw "not implemented"; }
virtual void visit(B& b) const { visit(static_cast<Abs&>(b)); }
virtual void visit(C& c) const { visit(static_cast<Abs&>(c)); }
};
struct Abs
{
virtual ~Abs() {}
virtual void hi() = 0;
virtual void accept(Visitor const& v) { v.visit(*this); }
};
struct B : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void bye() { ... }
};
struct C : Abs
{
void hi() { ... }
void accept(Visitor const& v) { v.visit(*this); }
void sayonara() { ... }
};
struct DoSayonara : Visitor
{
void visit(C& c) const { c.sayonara(); }
};
struct DoBye : Visitor
{
void visit(B& b) const { b.bye(); }
};
struct ByeOrSayonara : Visitor
{
void visit(B& b) const { b.bye(); }
void visit(C& c) const { c.sayonara(); }
};
and then you use
Abs* b = new B(); Abs* c = new C();
b->accept(DoSayonara()); // Throw an exception
c->accept(DoSayonara()); // Do what is expected
Do this only when you really need it.
If upcasting is compulsory and you need to call methods defined in the subclasses then You're Doing It Wrong.
However, at a given point in time, you either know that an object is a specific subclass, in which case you can dynamically cast to that type, or you don't and can't be sure you can call the function.
Assuming this is related to your other question, I've tried to explain a way to implement that particular problem in a different manner there.