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

目录
相关文章
|
2天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
35 18
|
3月前
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
45 0
|
2天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
30 13
|
2月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
121 5
|
2月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
125 4
|
2月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
172 4
|
3月前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
37 4
|
3月前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
38 4
|
3月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)
|
3月前
|
编译器 C++
【C++类和对象(中)】—— 我与C++的不解之缘(四)
【C++类和对象(中)】—— 我与C++的不解之缘(四)

热门文章

最新文章