简体   繁体   中英

How to pass a function from another class as parameter?

I want to pass a function from another class as parameter in my current class. I'm trying to do something like this (I siplified the code, so you still can get the idea):

B class:

bool B::myCmpFunc(int a, int b) {
    return a > b;
}

vector<int> B::sort(bool (*cmp)(int a, int b)) {
    vector<int> elems = getElems();
    for (int i = 0; i < elems.size() - 1; i++) {
        for (int j = i + 1; j < elems.size(); j++) {
            if ((*cmp)(elems[i], elems[j])) {
                int aux = elems[i];
                elems[i] = elems[j];
                elems[j] = aux;
            }
        }
    }
    return elems;
}

And I try to call this sort function from A class :

B b;
auto sortedElems = b.sort(&b.myCmpFunc);

The problem is I get this error when I try to pass &b.myCmpFunc as parameter in A class :

Error C2276 '&': illegal operation on bound member function expression

I also tried another things, like passing the function as b.myCmpFunct , B::myCmpFunc , &B::myCmpFunc , but I still got errors.

You mix up pointers to ordinary functions and pointer to member functions. Those are different concepts, that are worth understanding at some point. What you can do is to make the comparison function a static and then pass a pointer to it like this:

auto sortedElems = b.sort(&B::myCmpFunc);

Otherwise, you can implement myCmpFunc as a free function, ie, not bound to a class. Then pass it as

auto sortedElems = b.sort(&myFreeCmpFunc);

In any case, it doesn't make much sense to have a member function myCmpFunc that has no dependency on the state of its object. Making it a free function increases encapsulation and makes the comparison function reusable (apart from the fact that you could also use a std::greater<>{} function object instead.

When you have a class function (non static function inside a class), you need to pass this /the instance of the class around, so the compiler can pass this /the instance of the object to the function, when it invokes it.

You can:

  1. Make your function static . static functions inside a class don't use this / the object instance, so their pointers are normal.

static bool B::myCmpFunc(int a, int b) {}
b.sort(&b.myCmpFunc);
// or
b.sort(&B::myCmpFunc);
  1. You can refactor your function to use std::function and bind this with object pointer using std::bind .

vector<int> B::sort(std::function<bool(int a, int b)> cmp) {
        ... no changes ...
}
b.sort(std::bind(&B::myCmpFunc, &b, std::placeholders::_1, std::placeholders::_2));
  1. Refactor your function to take only B class functions.

vector<int> B::sort(bool (B::*cmp)(int a, int b)) {
       ...
       (this->*cmp)(...);
       ...
}
b.sort(&B::myCmpFunc);
  1. Use a lambda.

b.sort([](int a, int b) -> bool { return a < b; });
// really or
b.sort([&b](int a, int b) -> bool { return b.myCmpFunc(a, b); });
  1. and many more (ex. template).

As the member function B::myCmpFunc doesn't seem to use this pointer nor object members, I would go with declaring it static .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM