I have several behaviors that I want a class to have. I'd like to isolate these behaviors, so that I can reuse that code, mix and match at will.
For example, a way to do this would be:
class BehaviorAbstract {
protected:
virtual void processInfo(Info i) = 0;
}
class Behavior1: public BehaviorAbstract {
protected:
virtual void processInfo(Info i) { ... }
void performBehavior1() { ... }
}
class Behavior2: public BehaviorAbstract {
protected:
virtual void processInfo(Info i) { ... }
void performBehavior2() { ... }
}
class ConcreteObject: public Behavior1, Behavior2 {
protected:
void processInfo(Info i) {
// needs to call processInfo of Behavior1 and Behavior2
Behavior1::processInfo(i);
Behavior2::processInfo(i);
}
void perform() {
this->performBehavior1(); this->performBehavior2();
}
}
So here's the crux of the matter: ConcreteObject needs to call the 2 functions processInfo (same name, same arguments) of all the classes it inherits from. Imagine that all the behavior classes are coded by different developers. The function HAS to have the same name, because they all derive from BehaviorAbstract.
What's a reasonable design pattern to do this? I suspect multiple inheritance might be wrong here, and maybe a "multiple composition" would be better, but I need all the Behavior classes and the ConcreteObject to derive from BehaviorAbstract and they all need to operate on the same protected data member of BehaviorAbstract.
The solution I wrote above feels wrong and ugly. Is there a way to call automatically all the parent classes that implement processInfo, without explicitely having to rewrite their name?
Thanks a lot for the help.
If I got this right, then this question is about refactoring the ConcreteObject class.
Approach #1:
If you can make performBehavior() part of the BehaviorAbstract base class, then you can simply use a vector of BehaviorAbstract* and let polymorphism do its thing. I think this can be seen as the strategy pattern.
#include <iostream>
#include <vector>
typedef int Info;
struct BehaviorAbstract
{
virtual void processInfo(Info i) = 0;
virtual void performBehavior() = 0;
};
struct Behavior1 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior1::processInfo()" <<std::endl; }
void performBehavior() override
{ std::cout<< "Behavior1::performBehavior()" <<std::endl; }
};
struct Behavior2 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior2::processInfo()" <<std::endl; }
void performBehavior() override
{ std::cout<< "Behavior2::performBehavior()" <<std::endl; }
};
//------------------------------------------------//
struct ConcreteObject
{
typedef std::vector<BehaviorAbstract*> vec_behavior;
vec_behavior vba;
ConcreteObject(vec_behavior &&v) : vba(v)
{;}
void processInfo(Info i)
{
for (auto &&itr : vba)
itr->processInfo(i);
}
void perform()
{
for (auto &&itr : vba)
itr->performBehavior();
}
};
int main()
{
ConcreteObject foo = {{new Behavior1(), new Behavior2()}};
foo.processInfo(23);
foo.perform();
}
Example: https://rextester.com/UXR42210
Approach #2:
Using a variadic template which creates a tuple. The iterate over that tuple and run the functions. Again, if performBehavior1() and performBehavior2() could share the same function name, then it would get easier. The extra complexity here is that you need to write a manual way of iterating over that tuple. For simplicity, I called the processInfo() directly from the iterate_tuple struct.
#include <iostream>
#include <tuple>
typedef int Info;
struct BehaviorAbstract
{
virtual void processInfo(Info i) = 0;
};
struct Behavior1 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior1::processInfo()" <<std::endl; }
void performBehavior1()
{ std::cout<< "Behavior1::performBehavior1()" <<std::endl; }
};
struct Behavior2 : BehaviorAbstract
{
void processInfo(Info i) override
{ std::cout<< "Behavior2::processInfo()" <<std::endl; }
void performBehavior2()
{ std::cout<< "Behavior2::performBehavior2()" <<std::endl; }
};
//------------------------------------------------//
template<typename T, std::size_t N>
struct iterate_tuple
{
static void run(T &t, Info i)
{
std::get<N>(t).processInfo(i);
iterate_tuple<T, N-1>::run(t,i);
}
};
template<typename T>
struct iterate_tuple<T, 0>
{
static void run(T &t, Info i)
{
std::get<0>(t).processInfo(i);
}
};
//------------------------------------------------//
template<typename ...T>
struct ConcreteObject
{
std::tuple<T ...> tmp;
static constexpr std::size_t tuple_size = std::tuple_size<decltype(tmp)>::value;
ConcreteObject() : tmp{std::forward<T>(T()) ...}
{;}
void processInfo(Info i)
{
iterate_tuple<decltype(tmp), tuple_size-1>::run(tmp, i);
}
void perform()
{
std::get<0>(tmp).performBehavior1();
std::get<1>(tmp).performBehavior2();
}
};
int main()
{
ConcreteObject<Behavior1,Behavior2> foo;
foo.processInfo(23);
foo.perform();
}
Example: https://rextester.com/SBRE16218
Both approaches avoid multiple inheritance which, from what I understood, is what you want to avoid. FYI, the simpler the better.
Related
I am looking for a workaround to the lack of virtual template functions in C++.
What I want ideally is to be able to store my derived classes in a vector, iterate over those and call the correct function, so in pseudo-code:
template<typename T>
struct Output
{
...
};
struct Base
{
template<typename T>
virtual void doSomething(Output<T>& out) = 0;
};
struct DerivedA : public Base
{
DerivedA(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
struct DerivedB : public Base
{
DerivedB(const char* filename) {...}
template<typename T>
void doSomething(Output<T>& out) final
{
...
}
};
int main()
{
std::vector<Base*> vec;
vec.push_back(new DerivedA("data1.bin"));
vec.push_back(new DerivedB("data2.bin"));
vec.push_back(new DerivedA("data3.bin"));
vec.push_back(new DerivedA("data4.bin"));
Output<float> outF;
Output<double> outD;
Output<int> outI;
for (auto e : vec)
{
e->doSomething(outF);
e->doSomething(outD);
e->doSomething(outI);
}
return 0;
}
I would prefer it if the workaround is as "painless" and non-verbose as possible (since I am using the templates to avoid redefining the same function n times for n different types in the first place). What I had in mind was making myself a vtable with std::map, and doing some dynamic_casts. I am looking for any better ideas, or even for a concise implementation of that idea if you consider it the best in this scenario. I am looking for a solution that is ideally the least intrusive, and that is very easy to add new classes to.
Edit:
I figured a workaround, but it includes some verbosity (but at least avoids non-trivial code duplication):
struct Base
{
virtual void doSomething(Output<int>& out) = 0;
virtual void doSomething(Output<float>& out) = 0;
virtual void doSomething(Output<double>& out) = 0;
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "Base doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedA : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedA doSomething called with: " << typeid(T).name() << "\n";
}
};
struct DerivedB : public Base
{
void doSomething(Output<int>& out) final
{
doSomething<int>(out);
}
void doSomething(Output<float>& out) final
{
doSomething<float>(out);
}
void doSomething(Output<double>& out) final
{
doSomething<double>(out);
}
private:
template<typename T>
void doSomething(Output<T>& out)
{
std::cout << "DerivedB doSomething called with: " << typeid(T).name() << "\n";
}
};
Does anybody have any better idea how I can go about this without having to redefine the same functions over and over? Ideally it would be defined once in the base class, CRTP doesn't seem to help. Dynamic casts seem like the other sane option.
Try something like this:
struct OutputBase
{
virtual void doSomething() = 0;
};
template<class T >
struct Output : public OutputBase
{
virtual void doSomething()
{
std::cout << typeid(T).name();
}
};
struct Base
{
virtual void doSomething(OutputBase* out) = 0;
};
struct DerivedA : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedA doSomething called with: ";
out->doSomething();
std::cout<< std::endl;
}
};
struct DerivedB : public Base
{
virtual void doSomething(OutputBase* out)
{
std::cout << "DerivedB doSomething called with: ";
out->doSomething();
std::cout << std::endl;
}
};
int main()
{
OutputBase* out_int = new Output < int > ;
OutputBase* out_double = new Output < double >;
Base* a = new DerivedA;
a->doSomething(out_int);
a->doSomething(out_double);
Base* b = new DerivedB;
b->doSomething(out_int);
b->doSomething(out_double);
return 0;
}
You can use a wrapper around Output if you don't want to change it.
Currently I am learning about the Visitor Pattern and try out various ideas.
Below I have the code of my current setup, which I would like to get functioning somehow.
I would like to have two visitors, one that counts instances of Red and Blu separately and one that counts anything (one can assume, it's a Color)
This is of course solvable by simply implementing the second visitor analogously to the first one, however not using separate variables for counting, but just one.
I think however this is unnecessary - if I had for example many, many different colours, the code would be very repetitive: All functions in that visitor would be same, they would simply increment one variable. Surely, there is an easier way, but how?
According to the standard Visitor Pattern I have to implement for every color class a visit functions, thus this does not seem to be the right approach.
How would someone solve this problem?
#include <iostream>
class Color
{
public:
virtual void accept(class Visitor*) = 0;
};
class Red: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void eye()
{
std::cout << "Red::eye\n";
}
};
class Blu: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void sky()
{
std::cout << "Blu::sky\n";
}
};
class Visitor
{
public:
virtual void visit(Red*) = 0;
virtual void visit(Blu*) = 0;
};
class CountVisitor: public Visitor
{
public:
CountVisitor()
{
m_num_red = m_num_blu = 0;
}
/*virtual*/
void visit(Red*)
{
++m_num_red;
}
/*virtual*/void visit(Blu*)
{
++m_num_blu;
}
void report_num()
{
std::cout << "Reds " << m_num_red << ", Blus " << m_num_blu << '\n';
}
private:
int m_num_red, m_num_blu;
};
class TemplateVisitor: public Visitor
{
public:
TemplateVisitor() : num_of_colours(0) {}
/*virtual*/
template<class C>
void visit(C* c)
{
++num_of_colours;
}
void report_num()
{
std::cout << "Colours " << num_of_colours << '\n';
}
private:
int num_of_colours;
};
void Red::accept(Visitor *v)
{
v->visit(this);
}
void Blu::accept(Visitor *v)
{
v->visit(this);
}
int main()
{
Color *set[] =
{
new Red, new Blu, new Blu, new Red, new Red, nullptr
};
CountVisitor count_operation;
TemplateVisitor template_visitor;
for (int i = 0; set[i]; i++)
{
set[i]->accept(&count_operation);
set[i]->accept(&template_visitor);
}
count_operation.report_num();
template_visitor.report_num();
}
Unfortunately, virtual methods and template methods can't match.
I mean... if your base class Visitor require
virtual void visit(Red*) = 0;
virtual void visit(Blu*) = 0;
the implementation of two virtual methods in derived classes, you can't solve this obligation with a single template method
template<class C>
void visit(C* c)
{
++num_of_colours;
}
You have to write two methods, absolutely not template, with the exact signature. Maybe adding also override, to reduce the risk of mistakes.
void visit (Red * r) override
{ ++num_of_colours; }
void visit (Blu * b) override
{ ++num_of_colours; }
Obviously you can define a template method (maybe with another name, but also visit() if you want) that is called by both virtual overrided methods
template <typename C>
void visit (C * c)
{ ++num_of_colours; }
void visit (Red * r) override
{ visit<Red>(r); }
void visit (Blu * b) override
{ visit<Blu>(b); }
This way, you can implement the logic of the visitor in a single template method and call it by all virtual methods
Why not just use a map and add some function to color to use as an identifier?
class Color
{
public:
virtual void accept(class Visitor*) = 0;
virtual std::string color_name() = 0;
};
class Visitor
{
public:
virtual void visit(Color* c);
};
class CountVisitor: public Visitor
{
std::unordered_map<std::string, int> map;
public:
/*virtual*/
void visit(Color* c)
{
map[c.color_name()]++;
}
};
Let say I've this code with a EnvelopeMultiPoints class template:
#include <iostream>
#include <vector>
class EnvelopeMultiPointsBase
{
// base
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
void Process() {
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch> { };
template<typename T>
unsigned int EnvelopeMultiPoints<T>::mNumPoints = 5;
class Container
{
public:
EnvelopeMultiPointsBase *pAssociatedEnvelope;
Container(EnvelopeMultiPointsBase *associatedEnvelope) : pAssociatedEnvelope(associatedEnvelope) { }
~Container() { }
void Process();
private:
};
int main()
{
EnvelopeMultiPoints<Pitch> pitch;
Container container(&pitch);
container.pAssociatedEnvelope->Process();
}
And I want to pass to the Container any kind of "EnvelopeMultiPoints" types (a generic "pointer"), so later I can access to its own method (in my case, Process()).
Does it means that also Container must be templated? (which is huge in my real scenario; lot of works to transform all of its methods in template, translate header/cpp, and such).
Or is there a trick that I'm missing?
In few words: let say that I want to pass to Container EnvelopeMultiPoints<Pitch>, and than execute Process(). Later, I want to pass EnvelopeMultiPoints<Volume> instead, and than execute Process(). And so on. Is there a way to do this without converting also Container to a template?
The technique you need is called dynamic polymorphism
that is implemented in C++ by virtual functions.
Illustrating using your code:
class EnvelopeMultiPointsBase
{
public:
// Abstract base, no actual implementation
virtual void Process() = 0;
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
// Some specific implementation.
virtual void Process() override
{
std::cout << "process: " << mNumPoints << std::endl;
}
};
class Pitch : public EnvelopeMultiPoints<Pitch>
{
};
To call the Process function of the base class, you have to define it in the base class. You can move the implementation to templated child classes:
class EnvelopeMultiPointsBase
{
private:
virtual void ProcessImpl() = 0;
public:
void Process() {
//potential common code...
ProcessImpl();
//more potential common code...
}
};
template<class T>
class EnvelopeMultiPoints : public EnvelopeMultiPointsBase
{
public:
static unsigned int mNumPoints;
EnvelopeMultiPoints() { }
~EnvelopeMultiPoints() { }
private:
void ProcessImpl() {
std::cout << "process" << std::endl;
}
};
Consider the below code, EventGeneratorBase is a helper class intended to provide the actual implementation for AddEventHandler() and I would like to use that implementation in the class RemoteControl instead of explicity defining it. I know it's not possible to instantiate RemoteControl without defining the method but is there a shortcut or an easy way to avoid manually defining the methods.
Note: The code in it's present form doesn't compile because RemoteControl can't be instantiated.
#include <iostream>
#include <vector>
#include <memory>
template<class TEventHandler> struct IEventGenerator {
virtual ~IEventGenerator() = default;
virtual void AddEventHandler(std::weak_ptr<TEventHandler> eventHandler) = 0;
};
template <class TEvents> struct EventGeneratorBase : IEventGenerator<TEvents> {
void AddEventHandler(std::weak_ptr<TEvents> target) {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
struct IControlEvents {
virtual ~IControlEvents() = default;
virtual void PowerOn() = 0;
virtual void PowerOff() = 0;
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
virtual ~IRemoteControl() = default;
virtual void Toggle() = 0;
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
// I don't want to define AddEventHandler() in this class and
// would like to inherit the implementation from EventGeneratorBase
void Toggle() {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
t->PowerOn();
t->PowerOff();
}
}
}
};
struct Light : IControlEvents {
Light(std::string color) : _color(color) { }
void PowerOn() {
std::cout << _color << "::Light ON!" << std::endl;
}
void PowerOff() {
std::cout << _color << "::Light OFF!" << std::endl;
}
private:
std::string _color;
};
int main() {
std::shared_ptr<IRemoteControl> remote(new RemoteControl); // ERROR: Can't instantiate
std::shared_ptr<IControlEvents> light1(new Light("GREEN"));
std::shared_ptr<IControlEvents> light2(new Light("RED"));
remote->AddEventHandler(light1);
remote->AddEventHandler(light2);
remote->Toggle();
return 0;
}
Your problem is that you have two distinct sub-objects of type IEventGenerator<IControlEvents> within your RemoteControl object. One via EventGeneratorBase<IControlEvents> and one via IRemoteControl.
There are two ways to prevent you from having two distinct subobjects. The first is to inherit virtually from IEventGenerator<TEventHandler> in both spots. This has a modest run-time cost. Simply add virtual before every case of inheritance from IEventGenerator<?> and you are done.
A second method is to note that EventGeneratorBase is intended to help with implementing IEventGenerator.
template<class T> struct tag{using type=T;};
template<class Tag> using type_t=typename Tag::type;
template<class TEventHandler>
tag<TEventHandler> get_event_handler_type(
IEventGenerator<TEventHandler> const*
) { return {}; }
template<class X>
using event_handler_type = type_t< decltype( get_event_handler_type( (X*)nullptr ) ) >;
template <class Base, class TEvents = event_handler_type<Base>>
struct EventGeneratorHelper :
Base
{
void AddEventHandler(std::weak_ptr<TEvents> target) override {
_eventHandlers.push_back(target);
}
std::vector<std::weak_ptr<TEvents>> GetEventHandlers() {
return _eventHandlers;
}
private:
std::vector<std::weak_ptr<TEvents>> _eventHandlers;
};
now, go down to here:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
and change how we inherit. We now interpose EventGeneratorHelper between us and IRemoteControl, so they now share the same common IEventGenerator.
This removes the need for virtual inheritance, but does up your compile time, and can cause some executable code bloat.
We can go a step further. Add this to EventGeneratorHelper:
template<class Action>
void FireEvents( Action&& action ) const {
for (auto tref : GetEventHandlers()) {
auto t = tref.lock();
if (t) {
action(t);
}
}
}
which reduces RemoteControl to:
struct RemoteControl :
EventGeneratorHelper<IRemoteControl>
{
void Toggle() {
this->FireEvents([](std::shared_ptr<IRemoteControl> const& ptr){
t->PowerOn();
t->PowerOff();
});
}
};
which I think is nice -- requiring clients to know the right way of iterating seems silly.
You have a problem in your inheritance hierarchy.
template <class TEvents> struct EventGeneratorBase :IEventGenerator<TEvents> {
[...]
};
struct IRemoteControl : IEventGenerator<IControlEvents> {
[...]
};
struct RemoteControl : IRemoteControl, EventGeneratorBase<IControlEvents> {
[...]
};
This is not doing what you might expect. Instead, your class RemoteControl inherits twice from IEventGenerator, once from IRemoteControl and once from EventGeneratorBase.
Edit: Per some comments, by simple I mean a) less code, b) easy to maintain, and c) hard to get wrong.
Edit #2: Also, using containment instead of private inheritance is not objectionable if it does indeed simplify the implementation of InterfaceImpl.
Currently, the only way I know to do this is to have the implementer define the abstract method and delegate the call to the target base type's method. Example:
#include <iostream>
#include <memory>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
virtual void method1() { MethodOneImpl::method1(); }
virtual void method2(int x) { MethodTwoImpl::myFunc(x); }
};
int main()
{
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(0);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}
At first, I thought that perhaps this might solve the problem:
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
using MethodOneImpl::method1;
// Obviously this wouldn't work as the method names don't match.
//using MethodTwoImpl::???
};
The first using statement will make both MethodOneImpl::method1 methods be public, but it actually doesn't fulfill the contract with Interface, and it modifies the accessibility of MethodOneImpl::method1(int). And obviously we couldn't use this solution with method2 as the names don't match up.
FWIW, I have what I think is a solution, but it is not part of the standard at all (in other words it won't compile). I was thinking of making a proposal to the C++ committee; if anyone has any advice, I'd appreciate any comments below (but please dont' submit the advice as an answer).
An other option (at least if using MS VC++) is to use virtual inheritance:
struct MyInterface
{
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Method1Impl : public virtual MyInterface
{
virtual void Method1() { _tprintf( _T("Method1\n") ); }
};
class Method2Impl : public virtual MyInterface
{
virtual void Method2() { _tprintf( _T("Method2\n") ); }
};
class InterfaceImpl : public virtual MyInterface,
private Method1Impl,
private Method2Impl
{
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1();
pItf->Method2();
}
While this seems to work and satisfy what you are looking for (asside from C4250 warning that you will have to suppress with a #pragma), this wouldn't be my approach. (I believe virtual inheritance is still not something that supported across all compilers, but I could be wrong).
I would probably go with containment and once boilerplate code is identifier, wrap it into some kind of macro map (similar to maps in ATL or MFC) that would make it really, really difficult to ever screw it up.
So this would be my macro approach:
struct MyInterface
{
virtual float Method1( int x ) = 0;
virtual int Method2( float a, float b ) = 0;
virtual void Method3( const TCHAR* sz ) = 0;
};
class Method1Impl
{
public:
float Method1( int x ) {
_tprintf( _T("Method1: %d\n"), x ); return 5.0;
}
};
class Method2and3Impl
{
public:
int Method2( float a, float b ) {
_tprintf( _T("Method2: %f, %f\n"), a, b ); return 666;
}
void Method3( const TCHAR* sz ) {
_tprintf( _T("Method3: %s"), sz );
}
};
#define DECLARE_METHOD0( MethodName, Obj, R ) \
virtual R MethodName() { return Obj.MethodName(); }
#define DECLARE_METHOD1( MethodName, Obj, R, A1 ) \
virtual R MethodName( A1 a1 ) { return Obj.MethodName( a1 ); }
#define DECLARE_METHOD2( MethodName, Obj, R, A1, A2 ) \
virtual R MethodName( A1 a1, A2 a2 ) { return Obj.MethodName( a1, a2 ); }
class InterfaceImpl : public MyInterface
{
public:
DECLARE_METHOD1( Method1, m_method1Impl, float, int );
DECLARE_METHOD2( Method2, m_method2and3Impl, int, float, float );
DECLARE_METHOD1( Method3, m_method2and3Impl, void, const TCHAR* );
private:
Method1Impl m_method1Impl;
Method2and3Impl m_method2and3Impl;
};
void TestWeirdInterfaceImpl()
{
MyInterface* pItf = new InterfaceImpl();
pItf->Method1( 86 );
pItf->Method2( 42.0, 24.0 );
pItf->Method3( _T("hi") );
}
Until C++ gods grace us with variadic macros, you'll have to declare one for each number of parameters you have. Also if you used multiple inheritance, potentially you wouldn't need the second "Obj" param, but as I've said before, I'd avoid multiple inheritance if there's another solution, which in this case is one extra param.
Yet a third option could be something that authors of Pragmatic Programmer seem to advocate a lot. If you have a ton of cookie cutter code that you don't want to repeat because, as you pointed out, it introduces human error. Define your own language and write a code generator script (python, perl...) to auto-create the actual code. In this case you could almost point at an interface, and have the script write the text out for you. I haven't tried doing this kind of thing myself, but lately have been wanting to use it somewhere just to see and evaluate the outcome.
This is sort of ugly and may bloat the executable size, but what about
#include <iostream>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
template<typename T>
class MethodOneImpl : public T
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
template<typename T>
class MethodTwoImpl : public T
{
public:
void method2(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public MethodTwoImpl<MethodOneImpl<Interface> >
{
};
int main()
{
InterfaceImpl impl;
impl.method1();
impl.method2(0);
}
class AbsInterface
{
// this is a simple interface class.
public:
virtual void Method1() = 0;
virtual void Method2() = 0;
};
class Functor1
{
public:
void operator () ()
{
printf("This Is Void Functor1");
}
};
class Functor2
{
public:
void operator () ()
{
printf("This Is void Functor2");
}
};
template <class T1, class T2>
class DerivedTemplateClass : public AbsInterface
{
public:
virtual void Method1() { T1()(); }
virtual void Method2() { T2()(); }
};
void main()
{
DerivedTemplateClass<Stratege1, Stratege2> instance;
instance.Method1();
instance.Method2();
}
as you can see, I used Functor.
You could work with template and functor.
It seems impossible to bring MethodOneImpl / MethodTwoImpl into the scope of Interface without having them inherit from Interface because they will not fill the Virtual Table if they don't. C++ misses something like the keyword implements from other languages.
So you are stuck with the virtual inheritence thing unless realize/accept that what you are looking for is just a bridge pattern, which does not satisfy requirement a) (you shall write more code), midly b) (code not necessarly difficult to maintain) and may satisfy c).
Here (another) possible solution (with only method though to reduce bloat)
class Interface
{ public:
virtual void method1() {return impl_->method1();}
private:
Interface() {}
protected:
struct Impl {
virtual void method1() = 0; };
std::shared_ptr<Impl> impl_;
Interface(const std::shared_ptr<Impl> &impl) : impl_(impl) {}
};
class InterfaceImpl : public Interface
{
struct Impl : public Interface::Impl {
void method1() { std::cout << "InterfaceImpl::method1() " << std::endl; } } ;
public:
InterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl)) {}
};
template <class T>
class GenericInterfaceImpl : public Interface {
struct Impl : public Interface::Impl {
Impl( T &t) : t_(t) {}
void method1() { t_.method1() ; }
T t_; };
public:
GenericInterfaceImpl() : Interface(std::shared_ptr<Impl> (new Impl(T()))) {}
};
struct AMethod1Impl {
void method1() { std::cout << "AMethod1Impl::method1() " << std::endl; } } ;
struct AnotherMethod1Impl_not_working {
void method1_not_present() { std::cout << "AnotherMethod1Impl_not_working ::method1_not_present() " << std::endl; } } ;
int main() {
// compilation of next line would fail
// (lame attempt to simulate ompilation fail when pure function not implemented)
// Interface inf;
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf.reset(new GenericInterfaceImpl<AMethod1Impl>() );
inf->method1();
// compilation of next line would fail
// inf.reset(new GenericInterfaceImpl<AnotherMethod1Impl_not_working>() );
}
Does this serve your purpose?
It maintains the interface relationship and gives you maintainable code without having any consideration of client code.
Separating each method in functionoid and giving you the power to control the prototype of each method of the different base class.
#include <iostream>
#include <memory>
using namespace std;
//No Control over this.
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
//*************************//
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
//This is what i would do. //
class BaseFuncType
{
//no pure virtual
void Call()
{
throw "error";
}
void Call(int x)
{
throw "error";
}
};
class Method1: public BaseFuncType
{
auto_ptr<MethodOneImpl> MethodPtr;
public:
Method1()
{
MethodPtr.reset(new MethodOneImpl());
}
virtual int Call()
{
MethodPtr->method1();
}
};
class Method2: public BaseFuncType
{
auto_ptr<MethodTwoImpl> MethodPtr;
public:
Method2()
{
MethodPtr.reset(new MethodTwoImpl());
}
virtual int Call(int x)
{
MethodPtr->myFunc(x);
}
};
template <class T1>
class MethodFactory
{
private:
T1 methodObj;
public:
void CallMethod()
{
methodObj.Call();
}
void CallMethod(int x)
{
methodObj.Call(x);
}
};
class InterfaceImpl : public Interface
{
auto_ptr<MethodFactory> factory;
public:
virtual void method1()
{
factory.reset(new MethodFactory<Method1>());
factory->CallMethod();
}
virtual void method2(int x)
{
factory.reset(new MethodFactory<Method2>());
factory->CallMethod(x);
}
};
int main()
{
auto_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(10);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}