C++高级开发之可调用对象、function、bind(1)

简介: 可调用对象  以前函数调用总是离不开一堆圆括号,没错“()”就是函数调用的一个明显标记,这个 “()”有一个称呼叫函数调用运算符。

可调用对象

       07e2320bb649465785e379d4b78237ed.png                        

以前函数调用总是离不开一堆圆括号,没错“()”就是函数调用的一个明显标记,这个 “()”有一个称呼叫函数调用运算符

那么在类中重载了这个函数调用运算符“()”,就可以像使用函数一样是用那个该类的对象,或者换句话说就可以像函数调用一样来“调用”该类的对象

1.函数指针

  创建一个.cpp文件然后加入以下代码

void myfunc(int tv)
{
  cout << "myfunc()函数执行了,tv=" << tv << endl;
}

 在 main函数中加入如下代码

  void(*pmf)(int) = myfunc;
  pmf(20);

07e2320bb649465785e379d4b78237ed.png

2.具有 operator() 成员函数的类对象(仿函数/函数对象)

  仿函数的定义:仿函数又称为函数对象,是一个能行使函数功能的类所定义的对象。防寒输得语法几乎和普通的函数调用一样。

  在 cpp文件前面增加如下 TC类定义

class TC
{
public:
  void operator()(int tv)
  {
    cout << " TC::operator()执行了,tv=" << tv << endl;
  }
};

 在main函数中加入如下代码(可以选择将之前的main函数注释掉)

  TC tc;
  tc(20);//调用的是()操作符,这就是个可调用对象。等价于tc.operator()(20);


8eea4d9e58ce47c8bb1c8ec6d0438e04.png

3.可被转换为函数指针的类对象

  可被转换为函数值指针的类对象也可以叫做 仿函数或函数对象

  在 cpp文件中增加如下 TC2类定义

class TC2
{
public:
  using tfpoint = void(*)(int);
  static void mtsfunc(int tv) //静态成员函数
  {
    cout << "TC2::mysfunc()静态成员函数执行了,tv=" << tv << endl;
  }
  operator tfpoint() { return myfunc; }//类型转换运算符/类型转换函数
};

在main主函数中,加入如下代码

  TC2 tc2;
  tc2(30);

168fed1804104330a69720b236882a4c.png

4.类成员函数指针

  在前面的 TC类中增加一个 public修饰的成员函数和一个成员变量

public:
  void ptfunc(int tv)
  {
    cout << "TC::ptfunc()执行了,tv=" << tv << endl;
  };
  int m_a;

在 main主函数中加入如下代码

  TC tc3;
  void(TC::*myfpoint)(int) = &TC::ptfunc;//类成员函数指针变量 myfpoint定义并被给初值
  (tc3.*myfpoint)(999); //要调用你成员函数,就必须要用到对象 tc3


109006ea54ba4e5e83f1316c3a8bbb01.png

6.总结

  可调用对象首先被看做一个对象。那么有没有一种方法能够把这些可调用对象的调用形式统一起来呢?有,那就是使用 std::function 把这些可调用对象包装起来。

std::function 可调用对象包装器

 要使用这个类模板,在 cpp文件中要添加头文件 #include

 这个蕾姆办理装的是各种可调用对象,比较遗憾的是不能装类成员函数指针。因为类成员函数指针是需要类对象参与才能完成调用的。

  #include 类模板的特点是:**通过指定模板参数,它能够用统一的方式来处理各种可调用对象。

1.绑定普通函数

  在 main 主函数中加入如下代码

        //返回类型(参数列表)
  std::function<void(int)>f1 = myfunc;//绑定一个普通函数,注意<>中的格式
  f1(100);//调用普通函数


19454a10fef2493ea972dce187629d83.png

2绑定类的静态成员函数

  在前面的TC类中增加一个 public修饰的静态成员函数

  static int stcfunc(int tv)
  {
    cout << "TC::stcfunc()静态函数执行了,tv=" << tv << endl;
    return tv;
  }

在 main函数中加入如下代码

            //返回类型(参数列表)
  std::function<int(int)> fs2 = TC::stcfunc;
  fs2(110);

9770ea6c7f684ed99881c7cfe24196b3.png

3绑定仿函数

  在 main函数中,加入如下代码

  TC tc3;
  std::function<void(int)> f3 = tc3;//提示使用了未初始化的局部变量“tc3”,因为类TC里有成员变量没被初始化,需要增加一个构造函数,还应该初始化一下成员变量才好

35fcf8ed32cf404c9b9d8b2964ebade6.png

  在 TC类中增加 public修饰的构造函数并初始化成员变量 m_a

TC()  //构造函数
  {
    m_a = 1;
  }//加入之后不会再报错了

在 main主函数中,继续增加代码

  f3(120); //TC::operator()执行了, tv = 120
  TC2 tc4;
  std::function<void(int)> f4 = tc4;
  f4(150); //TC2::mysfunc()静态成员函数执行了, tv = 150

11f51b8724f244db985c0146b032ba7a.png

4范例演示

在 cpp文件 前面增加如下 CB类和 CT类定义

class CB
{
  std::function<void()> fcallback;
public:
  CB(const std::function<void()>& f) :fcallback(f)
  {
    int i;
    i = 1;
  }
  void runcallback(void)
  {
    fcallback();
  }
};
class CT
{
public: 
  CT()//构造函数
  {
    cout << "CT::CT()执行" << endl;
  }
  CT(const CT&)//拷贝构造函数
  {
    cout << "CT::CT(const CT&)执行" << endl;
  }
  ~CT()
  {
    cout << "CT::~CT()执行" << endl;
  }
  void operator()(void)
  {
    cout << "CT::opertor()执行" << endl;
  }
};

在 main函数中,加入如下代码:

  CT ct; //可调用对象,这行导致CT构造函数的执行
  CB cb(ct); //cb需要可调用对象做参数来构造,ct因为有operator()所以可以转为const std::function<void (void)> &对象。
           //这行导致CT拷贝构造函数被执行多次
  cb.runcallback(); //CT::opertor()执行

dcf5832e23ed4bf882bb50b29f1a24c0.png

再来一个范例,在 cpp前面增加如下代码

void mycallback(int cs, const std::function<void(int)>& f)
{
  f(cs);
}
void runfunc(int x)
{
  cout << x << endl;
}

在 main中函数中,加入如下代码:

    for (int i = 0; i < 10; i++)
    {
      mycallback(i, runfunc);//0,1,2,3,4,5,6,7,8,9
    }

a56c02d94b9f4222a61853b09af5e7c8.png

从范例中可以看出 std::function 的灵活性非常高,能容纳的可调用对象种类也非常多。

C++高级开发之可调用对象、function、bind(2)https://developer.aliyun.com/article/1415895?spm=a2c6h.13148508.setting.24.16254f0exsfwiz

目录
相关文章
|
5天前
|
存储 安全 编译器
【C++】类和对象(下)
【C++】类和对象(下)
【C++】类和对象(下)
|
4天前
|
编译器 C++
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
virtual类的使用方法问题之在C++中获取对象的vptr(虚拟表指针)如何解决
|
11天前
|
C++
C++ --> 类和对象(三)
C++ --> 类和对象(三)
26 9
|
5天前
|
编译器 C++
【C++】类和对象(中)
【C++】类和对象(中)
|
5天前
|
存储 编译器 程序员
【C++】类和对象(上)
【C++】类和对象(上)
|
6天前
|
存储 编译器 C++
【C++】类和对象(下)
【C++】类和对象(下)
|
6天前
|
存储 编译器 Linux
【C++】类和对象(上)
【C++】类和对象(上)
|
11天前
|
编译器 C++ 开发者
C++ --> 类和对象(二)
C++ --> 类和对象(二)
25 7
|
11天前
|
编译器 程序员 C语言
C++ --> 类和对象(一)
C++ --> 类和对象(一)
20 5
|
23天前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
【7月更文挑战第28天】在 Android 开发中, NDK 让 Java 与 C++ 混合编程成为可能, 从而提升应用性能。**为何选 NDK?** C++ 在执行效率与内存管理上优于 Java, 特别适合高性能需求场景。**环境搭建** 需 Android Studio 和 NDK, 工具如 CMake。**JNI** 构建 Java-C++ 交互, 通过声明 `native` 方法并在 C++ 中实现。**实战** 示例: 使用 C++ 计算斐波那契数列以提高效率。**总结** 混合编程增强性能, 但增加复杂性, 使用前需谨慎评估。
58 4

热门文章

最新文章