0

I have two very similar methods. Main difference between them is that they are calling another different method at some point. E.g.:

// method 1
method1(){
  // same code for Method1 and Method2 before calling different method
  methodA();
  // same code for Method1 and Method2 after calling different method
}

// method 2
method2(){
  // same code for Method1 and Method2 before calling different method
  methodB();
 // same code for Method1 and Method2 after calling different method
}

I want to create one method (method) which will be able to call both different methods (methodA and methodB). I guess this should be possible via polymorphism (if I'm wrong correct me please) e.g.:

method(Parent obj){
  // same code for Method1 and Method2 before calling different method
  obj->methodAB();
  // same code for Method1 and Method2 after calling different method
}

class Parent{
public:
  virtual int methodAB();
};

// methodA implementation
Class ChildA: public Parent{
public:
 int methodAB();
}

// methodB implementation
Class ChildB: public Parent{
public:
 int methodAB();
}

actual calling then will be:

Parent *obj = new ChildA; // or Parent *obj = new ChildB;
method1(obj)
delete obj;

But there is one serious problem: In my case methodA() and methodB() takes as argument different types, so my situation is actually:

method1(obj_type1){
  // same code for Method1 and Method2 before calling different method
  methodA(obj_type1);
  // same code for Method1 and Method2 after calling different method
}


method2(obj_type2){
  // same code for Method1 and Method2 before calling different method
  methodB(obj_type2);
 // same code for Method1 and Method2 after calling different method
}

Is it possible to implemented virtual function in derived classes with different types as arguments or is there any another elegant solution for this problem?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122
  • 1
    You are looking for the words "function pointer" – AndyG May 01 '17 at 21:55
  • 1
    You don't even need run-time polymorphism for this. Templates should work. – PaulMcKenzie May 01 '17 at 21:56
  • @AndyG function pointer can be replaced with polymorphism (which under the hood is using function pointer) http://www.cprogramming.com/tutorial/function-pointers.html – Wakan Tanka May 01 '17 at 21:56
  • @PaulMcKenzie I guess yes but I do not know how to correctly implement them. Actually my `methodA` and `methodB` are for sorting and here http://stackoverflow.com/questions/7264402/when-to-use-template-vs-inheritance is following statement: Templates on the other hand are "horizontal" and define parallel instances of code that knowns nothing of each other. Sorting integers is formally the same as sorting doubles and sorting strings, but those are three entirely different functions. They all "look" the same from afar, but they have nothing to do with each other. – Wakan Tanka May 01 '17 at 21:59
  • Where do `object_type1` and `object_type2` come from? Are they passed into `Method1` and `Method2` from the outside? If they're not, then the code isn't exactly the same? – Donnie May 01 '17 at 22:03
  • @Donnie they could be global. – user2141130 May 01 '17 at 22:04
  • @user2141130 The could be, but we're also guessing. – Donnie May 01 '17 at 22:04
  • "so my situation is actually" - barely resembling what you originally claimed. Those are apples and oranges. Start with what you *really* have: two different members taking two distinctly unique parameter types. – WhozCraig May 01 '17 at 22:05
  • @Donnie OP modified – Wakan Tanka May 01 '17 at 22:06
  • @WakanTanka [This is a simple example](http://coliru.stacked-crooked.com/a/97020fcebea669dc) using templates. More customization -- add policies. – PaulMcKenzie May 01 '17 at 22:10
  • Whether you want to use function pointers or polymorphism, the function signatures must match. The only way I know to try to get around this in C++ is to use Boost::Any if that is acceptable. – user2141130 May 01 '17 at 22:13
  • @user2141130 The signatures need not match if templates are used. And even so, a functor class that knows its own internals, and a call to its `operator()` is another way to get around the signature issue. – PaulMcKenzie May 01 '17 at 22:17
  • It looks like @PaulMcKenzie and I had the same idea, just different online compilers and slightly different approaches. :) – Donnie May 01 '17 at 22:23
  • @PaulMcKenzie templates don't allow dynamic polymorphism, and I think dynamic polymorphism is what the OP wants. If I'm wrong and static polymorphism is ok then I agree. – user2141130 May 01 '17 at 22:54

2 Answers2

2

So refactor the common code to some other functions, and call those from both methods (member functions):

method1(){
  common_code_1();
  auto result = methodA(obj_type1);
  common_code_2(result);
}


method2(){
  common_code_1();
  auto result = methodB(obj_type2);
  common_code_2(result);

}
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • this is not so easy because I'm calling `methodA` and `methodB` from inside loop and the next code flow (break, continue or "normal" loop ending) is depended on `methodA` and `methodB` result. – Wakan Tanka May 01 '17 at 22:02
  • You can of course pass the result of `methodA` or `methodB` to `common_code_2`. I've added that to my example. – Bo Persson May 02 '17 at 08:27
1

You can use templates to do what you want, something along these lines:

void foo1(int i)
{

}

void foo2(double d)
{

}

template<typename ArgType, void (*Func)(ArgType arg)>
void DoIt(ArgType a)
{
  // Common 1
  Func(a);   
  // Common 2
}

int main()
{
    DoIt<int, foo1>(1);
    DoIt<double, foo2>(1.0);

   return 0;
}

Func doesn't need to be void, it can return a bool or whatever if that's what you need for your processing.

Donnie
  • 45,732
  • 10
  • 64
  • 86
  • 1
    That was my suggestion in the comments, so I'll upvote ; Also, if the argument count in `Func` is different, passing a functor and calling its `operator()` is one way to get around the argument count issue. – PaulMcKenzie May 01 '17 at 22:22