C++成员函数当作参数调用的两种方式

     平时编程时,多用来将数据进行传参,在考虑回调场景下我们会将函数单做参数传给被调用函数,让被调用函数在时机成熟时进行调用。在某些场景下,需要将类的成员函数当作参数进行回调,此时定义成员函数形参的方式通常有两种,以一种是成员函数指针类型,另外一种是使用std::function函数包装器。

目录

1. C++常见的可调用对象

(1) 普通函数

(2) lambda表达式

(3) 函数对象类

(4) 类的静态成员函数

(5) 类的普通成员函数

2. 成员函数指针当作形参调用成员函数

3. std::function作为形参调用成员函数


1. C++常见的可调用对象

(1) 普通函数

int MyAdd(int num1, int num2){ return num1+num2; }

(2) lambda表达式

auto MyMod = [](int num1, int num2){ return num1%num2; };

(3) 函数对象类

struct MyDivide{
    int operator()(int num1, int num2){
        return num1/num2;
    }
};

(4) 类的静态成员函数

class MyMul {
public:
    static int mul(int num1, int num2) {
        return num1*num2;
    }
};

(5) 类的普通成员函数

class MyClass {
public:
    void show(const int &num1 = 100, const int &num2 = 300) {
        std::cout << num1 << " +-*/ " << num2 << std::endl;
    }
};

调用方式:

void testCanCallFunc() {
    std::function<int(int, int)>  a = MyAdd; 
    std::function<int(int, int)>  b = MyMod; 
    std::function<int(int, int)>  c = MyDivide();
    std::function<int(int, int)>  d = MyMul::mul;
    MyClass myClass;
    std::function<void(const int&, const int&)>  e = std::bind(&MyClass::show, &myClass, std::placeholders::_1, 9527);
    std::function<void(const int&, const int&)>  f = std::bind(&MyClass::show, &myClass, std::placeholders::_1, std::placeholders::_2);

    std::cout << a(111, 222) << std::endl;
    std::cout << b(100, 200) << std::endl;
    std::cout << c(200, 300) << std::endl;
    std::cout << d(777, 888) << std::endl;
    e(1, 2);
    f(4, 5);

    auto fun1 = [] (int a1, int a2) {
    std::cout << a1 << "  " << a2 << std::endl;
    };

    auto myFun = [a, b, c, fun1](int a1, int a2){
        std::cout << a(a1, a2) << std::endl;
        std::cout << b(a1, a2) << std::endl;
        std::cout << c(a1, a2) << std::endl;
        fun1(a1, a2);
    };
    myFun(111, 333);
}

调用结果:

2. 成员函数指针当作形参调用成员函数

如下定义两个类:

class TestClass1 {
public:
  TestClass1() {}
  ~TestClass1() {}
  void fun() { std::cout << __FUNCTION__ << std::endl; }
  void fun1() { std::cout << __FUNCTION__ << std::endl; }
private:

};

class TestClass2 {
public:
  TestClass2() {}
  ~TestClass2() {}
  void fun() { std::cout << __FUNCTION__ << std::endl; }
  void fun1() { std::cout << __FUNCTION__ << std::endl; }
  void fun2(const int& num) { std::cout << __FUNCTION__ << " " << num << std::endl; }
private:

};

调用其成员函数:

//成员函数指针形式参数,此处abxd和exf是形参数名字,可以随便起名字
void CallMemberFun(TestClass1& t1, void (TestClass1::*abxd)(), 
                    TestClass2 t2, void (TestClass2::*exf)(),
                    void (TestClass2::*hello)(const int &a), 
                    const int& num = 1234) {
  (t1.*abxd)();
  (t2.*exf)();
  (t2.*hello)(num);
}

void testUseClassMemFunc() {
  TestClass1 t1 = TestClass1();
  CallMemberFun(t1, &TestClass1::fun1, TestClass2(), 
                      &TestClass2::fun, 
                      &TestClass2::fun2);
}

调用结果:

3. std::function作为形参调用成员函数

//std::function充当形式参数,通过std::bind转换成员函数为std::function类型,来实现对成员函数的调用
void CallMemberFun(std::function<void()> abxd, 
                    std::function<void()>exf,
                    std::function<void(const int&)> hello, 
                    const int& num = 1234) {
  abxd();
  exf();
  hello(num);
}

void testUseClassMemUseFunciton() {
  TestClass1 t1 = TestClass1();
  auto aFun = std::bind(&TestClass1::fun1, &t1);
  TestClass2 t2 = TestClass2(); 
  auto aFun2 = std::bind(&TestClass2::fun2, &t2, std::placeholders::_1);
  CallMemberFun(aFun, std::bind(&TestClass1::fun1, &t1), aFun2, 7788); 
}

调用结果如下:

附录:

完整代码:

#include <iostream>
#include <functional>

//普通函数
int MyAdd(int num1, int num2){ return num1+num2; } 

//lambda表达式
auto MyMod = [](int num1, int num2){ return num1%num2; };

//函数对象类
struct MyDivide{
    int operator()(int num1, int num2){
        return num1/num2;
    }
};

//类的静态成员函数
class MyMul {
public:
static int mul(int num1, int num2) {
    return num1*num2;
    }
};

//普通类的成员函数
class MyClass {
public:
    void show(const int &num1 = 100, const int &num2 = 300) {
        std::cout << num1 << " +-*/ " << num2 << std::endl;
    }
};

class TestClass1 {
public:
  TestClass1() {}
  ~TestClass1() {}
  void fun() { std::cout << __FUNCTION__ << std::endl; }
  void fun1() { std::cout << __FUNCTION__ << std::endl; }
private:

};

class TestClass2 {
public:
  TestClass2() {}
  ~TestClass2() {}
  void fun() { std::cout << __FUNCTION__ << std::endl; }
  void fun1() { std::cout << __FUNCTION__ << std::endl; }
  void fun2(const int& num) { std::cout << __FUNCTION__ << " " << num << std::endl; }
private:

};

//成员函数指针形式参数,此处abxd和exf是形参数名字,可以随便起名字
void CallMemberFun(TestClass1& t1, void (TestClass1::*abxd)(), 
                    TestClass2 t2, void (TestClass2::*exf)(),
                    void (TestClass2::*hello)(const int &a), 
                    const int& num = 1234) {
  (t1.*abxd)();
  (t2.*exf)();
  (t2.*hello)(num);
}


//std::function充当形式参数,通过std::bind转换成员函数为std::function类型,来实现对成员函数的调用
void CallMemberFun(std::function<void()> abxd, 
                    std::function<void()>exf,
                    std::function<void(const int&)> hello, 
                    const int& num = 1234) {
  abxd();
  exf();
  hello(num);
}

void testCanCallFunc() {
    std::function<int(int, int)>  a = MyAdd; 
    std::function<int(int, int)>  b = MyMod; 
    std::function<int(int, int)>  c = MyDivide();
    std::function<int(int, int)>  d = MyMul::mul;
    MyClass myClass;
    std::function<void(const int&, const int&)>  e = std::bind(&MyClass::show, &myClass, std::placeholders::_1, 9527);
    std::function<void(const int&, const int&)>  f = std::bind(&MyClass::show, &myClass, std::placeholders::_1, std::placeholders::_2);

    std::cout << a(111, 222) << std::endl;
    std::cout << b(100, 200) << std::endl;
    std::cout << c(200, 300) << std::endl;
    std::cout << d(777, 888) << std::endl;
    e(1, 2);
    f(4, 5);

    auto fun1 = [] (int a1, int a2) {
    std::cout << a1 << "  " << a2 << std::endl;
    };

    auto myFun = [a, b, c, fun1](int a1, int a2){
        std::cout << a(a1, a2) << std::endl;
        std::cout << b(a1, a2) << std::endl;
        std::cout << c(a1, a2) << std::endl;
        fun1(a1, a2);
    };
    myFun(111, 333);
}

void testUseClassMemFunc() {
  TestClass1 t1 = TestClass1();
  CallMemberFun(t1, &TestClass1::fun1, TestClass2(), 
                      &TestClass2::fun, 
                      &TestClass2::fun2);
}

void testUseClassMemUseFunciton() {
  TestClass1 t1 = TestClass1();
  auto aFun = std::bind(&TestClass1::fun1, &t1);
  TestClass2 t2 = TestClass2(); 
  auto aFun2 = std::bind(&TestClass2::fun2, &t2, std::placeholders::_1);
  CallMemberFun(aFun, std::bind(&TestClass1::fun1, &t1), aFun2, 7788); 
}

int main(int argc, char *argv[]) {
    testCanCallFunc();
    std::cout << "===================================" << std::endl;
    testUseClassMemFunc();
    std::cout << "===================================" << std::endl;
    testUseClassMemUseFunciton();
	return 0;
}

运行结果如下:

猜你喜欢

转载自blog.csdn.net/hsy12342611/article/details/128417090
今日推荐