1

I am developing a project where I want it to be possible to specify which of several classes of methods/algorithms/functions is to be used. Each method "class" provides similar functions, and is interchangeable with the other classes.

I tried to implement this with a base abstract class with the method "classes" as derived classes:

class Method {
public:
    virtual int function1(int) = 0;
    virtual int function2(int, int) = 0;
};

class Method1 : public Method {
public:
    int function1(int a) {
        return a * 2;
    }

    int function2(int a, int b) {
        return a + b;
    }
};

class Method2 : public Method {
public:
    int function1(int a) {
        return a / 2;
    }

    int function2(int a, int b) {
        return a - b;
    }
};

void useMethod(int a, int b, Method& m) {
    int result1 = m.function1(a);
    int result2 = m.function2(a, b);

    /* Do something with the results here */
}

int main() {
    // Doesn't work, "type name is not allowed"
    useMethod(1, 2, Method1);
    useMethod(1, 2, Method2);

    // Works, but seems unnecessary and less elegant
    Method1 x;
    useMethod(1, 2, x);
    Method2 y;
    useMethod(1, 2, y);

    return 0;
}

The problem is that I can't seem to figure out how to allow using Method1 and Method2 without creating instances of them - which seems to me unnecessary, since they'll all just provide the same functions. Is there some way to make derived classes sort of "static" so they can be utilised without instances?

MC ΔT
  • 483
  • 5
  • 12
  • 1
    Possible duplicate of http://stackoverflow.com/questions/1820477/c-static-virtual-members – UnholySheep Jan 01 '17 at 10:38
  • Also I don't think inheritance is quite the right approach here. I think using templates and/or function pointers (or `std::function`) would make more sense – UnholySheep Jan 01 '17 at 10:39
  • @UnholySheep Could you elaborate on how `std::function` could provide a better solution? Isn't that just a function wrapper? – MC ΔT Jan 01 '17 at 11:47
  • 1
    It was just a thought, depending on your exact requirements you might consider using containers of function pointers or functors (e.g.: something involving a `std::map` or similar). Or consider passing individual functions to other methods (instead of an entire class/object). However the template approach (as in the answer below) is most likely your best choice – UnholySheep Jan 01 '17 at 11:53

1 Answers1

4

You could do just:

useMethod(1, 2, Method1());
useMethod(1, 2, Method2());

Otherwise no, you cannot have static virtual methods. You could achieve similar thing with templates though:

template<typename T>
void useMethod(int a, int b) 
{
    int result1 = T().function1(a); //or if you made the methods static then T::method1(a)
    int result2 = T().function2(a, b); //ditto

    /* Do something with the results here */
}

And usage:

useMethod<Method1>(1, 2);

And you do not need the base abstract class then and no need for virtual methods either. As mentioned in the code comment you can make the methods static and will then not need instance(s) of the class(es).

Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
Resurrection
  • 3,916
  • 2
  • 34
  • 56
  • It's worth mentioning that that is essentially the same as OPs second attempt, except you create the objects directly in the function call instead of assigning them to variables first. – UnholySheep Jan 01 '17 at 10:45
  • @UnholySheep Yes, it was meant as proof that it is not "less elegant". Added the template version anyway to show alternative approach without the polymorphism. – Resurrection Jan 01 '17 at 10:46