六一的部落格


关关难过关关过,前路漫漫亦灿灿。



C++中的可调用对象:

  1. 函数
  2. 函数指针
  3. bind创建的对象
  4. 重载了函数调用运算符的类
  5. lambda表达式

可调用对象具有类型:

类型
lambda表达式 未命名类类型
函数和函数指针 返回值和实参类型决定
函数 函数类型
函数指针 函数指针类型
重载了函数调用运算符的类 类类型
bind创建的对象

调用形式

call signature

不同类型的可调用对象可以共享同一种调用形式, 调用形式由返回类型和形参列表决定

如:

int(int, int)

支持该调用形式的可调用对象如:

  1. 函数
  2. lambda表达式
  3. 重载了函数调用运算符的类
 1int add(int i, int j) { return i + j; }
 2
 3auto mod = [](int i, int j) { return i % j; };
 4
 5struct divide
 6{
 7    int operator() (int denominator, int divisor)
 8    {
 9        return denominator / divisor;
10    }
11};

存放函数指针的函数表

function table

使用关联容器map存储指向函数的指针, 当程序需要执行某个特定操作时, 从表中查找该调用的函数

构建从运算符到函数指针的映射

1int add(int i, int j) { return i + j; }
2
3auto mod = [](int i, int j) { return i % j; };
4
5map<string, int(*)(int, int)> binops;
6
7binops.insert({"+", add});
8
9binops.insert({"%", mod});        // 错误:mod类型为类类型

function类

模板类

function对象可以存储给定调用形式的可调用对象, 对可调用对象进行了统一


头文件

1#include <functional>

初始化

  1. 默认初始化
    1function<T> f;
  2. 显式构造空function
    1function<T> f(nullptr);
  3. 使用可调用对象初始化function
    1function<T> f(obj);

示例

1function<int(int, int)> f1 = add;                                      // 函数名
2function<int(int, int)> f2 = divide();                                 // divide类的对象
3function<int(int, int)> f3 = [](int i, int j) { return i % j; };       // lambda表达式
4
5cout << f1(4, 2) << endl;
6cout << f2(4, 2) << endl;
7cout << f3(4, 2) << endl;

条件判断

f有可调用对象为真; 假

1f;

调用

使用参数args调用f中的对象

1f(args);

类型成员

-
result_type 可调用对象的返回类型
argument_type 可调用对象只有一个实参: 实参类型
first_argument_type 可调用对象有两个实参: 第一个实参类型
second_arugment_type 可调用对象有两个实参: 第二个实参类型

存放function对象的函数表

 1map<string, function<int(int, int)>> binops = {
 2    {"+", add},                                        // 函数名
 3    {"-", minus<int>()},                               // 标准库函数对象 
 4    {"/", divide()},                                   // 自定义函数对象
 5    {"*", [](int i, int j) { return i * j; }},         // lambda表达式 
 6    {"%", mod}                                         // lambda对象 
 7};
 8
 9binops["+"](10, 5);
10
11// 通过关键字调用可调用对象

function与重载函数

如果有对函数进行重载, 因为二义性的问题, function对象存储函数指针而非函数名

  1. 二义性
    1int add(int i, int j) { return i + j; }
    2Sales_data add(const Sales_data&, const Sales_data&);
    3map<string, function<int(int, int)>> binops;
    4binops.insert({"+", add});                                // 存在二义性问题
    
  2. 使用函数指针
    1int (*fp)(int, int) = add;
    2binops.insert({"+", fp});
    也可以使用lambda表达式, 在lambda函数体中调用目标函数
    1binops.insert({"+", [](int i, int j) { return add(i, j); }});

标准库: function类


C++中的可调用对象:

  1. 函数
  2. 函数指针
  3. bind创建的对象
  4. 重载了函数调用运算符的类
  5. lambda表达式

可调用对象具有类型:

类型
lambda表达式 未命名类类型
函数和函数指针 返回值和实参类型决定
函数 函数类型
函数指针 函数指针类型
重载了函数调用运算符的类 类类型
bind创建的对象

调用形式

call signature

不同类型的可调用对象可以共享同一种调用形式, 调用形式由返回类型和形参列表决定

如:

int(int, int)

支持该调用形式的可调用对象如:

  1. 函数
  2. lambda表达式
  3. 重载了函数调用运算符的类
 1int add(int i, int j) { return i + j; }
 2
 3auto mod = [](int i, int j) { return i % j; };
 4
 5struct divide
 6{
 7    int operator() (int denominator, int divisor)
 8    {
 9        return denominator / divisor;
10    }
11};

存放函数指针的函数表

function table

使用关联容器map存储指向函数的指针, 当程序需要执行某个特定操作时, 从表中查找该调用的函数

构建从运算符到函数指针的映射

1int add(int i, int j) { return i + j; }
2
3auto mod = [](int i, int j) { return i % j; };
4
5map<string, int(*)(int, int)> binops;
6
7binops.insert({"+", add});
8
9binops.insert({"%", mod});        // 错误:mod类型为类类型

function类

模板类

function对象可以存储给定调用形式的可调用对象, 对可调用对象进行了统一


头文件

1#include <functional>

初始化

  1. 默认初始化
    1function<T> f;
  2. 显式构造空function
    1function<T> f(nullptr);
  3. 使用可调用对象初始化function
    1function<T> f(obj);

示例

1function<int(int, int)> f1 = add;                                      // 函数名
2function<int(int, int)> f2 = divide();                                 // divide类的对象
3function<int(int, int)> f3 = [](int i, int j) { return i % j; };       // lambda表达式
4
5cout << f1(4, 2) << endl;
6cout << f2(4, 2) << endl;
7cout << f3(4, 2) << endl;

条件判断

f有可调用对象为真; 假

1f;

调用

使用参数args调用f中的对象

1f(args);

类型成员

-
result_type 可调用对象的返回类型
argument_type 可调用对象只有一个实参: 实参类型
first_argument_type 可调用对象有两个实参: 第一个实参类型
second_arugment_type 可调用对象有两个实参: 第二个实参类型

存放function对象的函数表

 1map<string, function<int(int, int)>> binops = {
 2    {"+", add},                                        // 函数名
 3    {"-", minus<int>()},                               // 标准库函数对象 
 4    {"/", divide()},                                   // 自定义函数对象
 5    {"*", [](int i, int j) { return i * j; }},         // lambda表达式 
 6    {"%", mod}                                         // lambda对象 
 7};
 8
 9binops["+"](10, 5);
10
11// 通过关键字调用可调用对象

function与重载函数

如果有对函数进行重载, 因为二义性的问题, function对象存储函数指针而非函数名

  1. 二义性
    1int add(int i, int j) { return i + j; }
    2Sales_data add(const Sales_data&, const Sales_data&);
    3map<string, function<int(int, int)>> binops;
    4binops.insert({"+", add});                                // 存在二义性问题
    
  2. 使用函数指针
    1int (*fp)(int, int) = add;
    2binops.insert({"+", fp});
    也可以使用lambda表达式, 在lambda函数体中调用目标函数
    1binops.insert({"+", [](int i, int j) { return add(i, j); }});