1

atm I'm trying to find the best solution for creating objects(classes) with common properties but differ in one specific function. The reason I dont use a simple sub-class is, that I have about 50 "different" objects and I do not want to create a class for each of them.

Here is my attempt to do so:

class module{
public:
  //..constructor and stuff
  void (*work)();
}

int main(){
  module A = new module();
  A->work = [](mainclass* m_class) -> void {/*do smth specific */});
  //... continue with B,C,...
}

I wonder if this is the most elegant (or most horrible) way to do this, or if there is a better concept for that kind of task.

Die Usche
  • 132
  • 10
  • 2
    Any reason why you can't use the standard OO approach of making `void module::work(mainclass*)` a virtual function in `module`, and then deriving a different base class for each different implementation? You would then need `m_ModuleList` to be a vector of pointers to `module` (or `unique_ptr` or `smart_ptr`, etc.) – j_random_hacker Jul 29 '14 at 22:33
  • Jeah I wanted to avoid creating 50 different sub-classes for just one (in most cases pretty short) function – Die Usche Jul 29 '14 at 22:37
  • @DieUsche: The function is always known at compile time? Do the objeccts _have_ to be of the same class? Can that class be a template where the template parameter is the function to be called? – Mooing Duck Jul 29 '14 at 23:30
  • 2
    `std::function work;` would be more flexible than `void (*work)();` – aschepler Jul 29 '14 at 23:32
  • yes, the function of the module is always known at compiletime. And no, the objects just have to be childs of a masterclass to store them in a STL. What do you mean exactly with "class be a template function"? – Die Usche Jul 29 '14 at 23:33
  • 1
    @DieUsche: If they're stored in a container, then the compiler doesn't know which object is attached to which function, since they'll all have the same type, so the function of `container[0]` is _not_ known at compile time. (If you need it to be, you can use a `tuple` instead) – Mooing Duck Jul 30 '14 at 00:00
  • Whatever you do, ***don't*** store derived objects in an STL container of base class type -- this causes [object slicing](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c), i.e. badness that the compiler won't object to. – j_random_hacker Jul 30 '14 at 00:18

2 Answers2

5

If the class doesn't have to be exactly the same, use templates

template<void(*work_fn)(mainclass*)>
class module{
public:
  //..constructor and stuff
  void work(mainclass* p) {work_fn(p);}
};

void work_A(mainclass*) {/*do smth specific */};

int main(){
  module<work_A> A; //note, no new
  A.work(thingy);
}

If you do have to use exactly the same type (sometimes), then you can use dynamic dispatch on your class:

class module {
public:
  //..constructor and stuff
  virtual void work(mainclass* p);
};
template<void(*work_fn)(mainclass*)>
class module_impl : public module {
public:
  using module;
  void work(mainclass* p) {work_fn(p);}
};

void work_A(mainclass*) {/*do smth specific */};

int main(){
  std::unique_ptr<module> A(new module_impl<work_A>(););
  A->work(thingy);
}

However, this might be overkill. Your idea may indeed be best if they're being stored in a container or whatever.

class module{
public:
  //..constructor and stuff
  explicit module(std::function<void(mainclass*)> workfunc) : work(std::move(workfunc)) {}

  std::function<void(mainclass*)> work;
};

int main(){
  module A([](mainclass* m_class) -> void {/*do smth specific */}); //note no new
  A.work(thingy);
}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
0

There is a famous software design pattern called the "strategy pattern", which is probably what you want: changing behaviour at runtime. A nice tutorial (although for java, but immediately translatable to C++) is here https://www.youtube.com/watch?v=-NCgRD9-C6o&list=PLF206E906175C7E07&index=3

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • sorry, basic inheritance patterns were not the thing I was looking for, but a nice video for beginners though – Die Usche Jul 29 '14 at 22:40
  • @DieUsche, I may have put an incorrect link, there are a variety of design patters explained, one of them is the strategy patter, which uses composition not inheritance. Updated the link – vsoftco Jul 29 '14 at 22:42
  • Ah lright, I guess I will read through some articles refering to "strategy pattern" then ;) – Die Usche Jul 29 '14 at 22:44
  • I read through the basics and it's definately a more elegant way than mine. The thing is I don't really need to change behavior at runtime, so maybe there is a way to just do the task at compiletime (maybe through templates), but nice advice though! – Die Usche Jul 29 '14 at 22:52