• Index

函数类型

Reads: 22

函数类型

函数实际上也是一个值,也就是说,函数可以用变量来保存,而这个变量的数据类型是std::functionstd::function是一个类,它在functional标准库中。

假设要保存函数int myabs(int num);,那么就需要使用数据类型std::fuction<int(int)>,即在std::function<>里面填返回值(参数类型),完整的赋值语句是std::function<int(int)> myfunc = myabs;。当然也可以用auto来声明变量:auto myfunc = myabs;

简短的示例:

int myabs(int num); // 声明函数
std::function<int(int)> myfunc = myabs; // 用变量myfunc保存myabs函数
myabs(-1024); // 函数的调用
myfunc(-2333); // 这时候myfunc也是函数,调用方法和上面myabs一样

以下讲解函数类型的用途,即为什么要用函数类型。先看几个问题。

写一个函数,函数声明是这样的:unsigned int count_gu(std::u32string text);;功能是用来统计指定字符串中有多少个字;函数有一个参数text,就是需要被统计的字符串;返回类型是unsigned int,代表字符串中有多少个字。

基础示例 1

#include <iostream> // std::cout std::endl
#include <string> // std::u32string

// 以下是统计函数的使用说明
// 功能: 统计指定字符串中有多少个古字
// 参数: 需要被统计的字符串
// 返回值: 字符串中古字的数量
unsigned int count_gu(std::u32string text);

int main(void)
{
    // 统计字符串中一共有多少个古字
    auto numofgu = count_gu(U"小古银小古银我是美美哒小古银");
    std::cout << R"raw(字符串有多少个古字:)raw" << numofgu << std::endl;
    return 0;
}

unsigned int count_gu(std::u32string text)
{
    // 遍历字符串中所有字符, 如果符合条件则统计
    unsigned int count = 0; // 用来保存统计数量
    for (auto ch : text)
    {
        if (ch == U'古')
        {
            ++count;
        }
    }

    // 返回统计数量
    return count;
}

输出结果:

字符串有多少个古字:3

再写一个函数,函数声明是这样的:unsigned int count_guyin(std::u32string text);;功能是用来统计字和字在指定字符串中一共有多少个;函数有一个参数text,就是需要被统计的字符串;返回类型是unsigned int,代表字符串中一共有多少个字和字。

基础示例 2

#include <iostream> // std::cout std::endl
#include <string> // std::u32string

// 以下是统计函数的使用说明
// 功能: 统计指定字符串中一共有多少个古字和银字
// 参数: 需要被统计的字符串
// 返回值: 字符串中古字和银字的数量
unsigned int count_guyin(std::u32string text);

int main(void)
{
    // 统计字符串中一共有多少个古字
    auto numofguyin = count_guyin(U"小古银小古银我是美美哒小古银");
    std::cout << R"raw(字符串有多少个古字和银字:)raw" << numofguyin << std::endl;
    return 0;
}

unsigned int count_guyin(std::u32string text)
{
    // 遍历字符串中所有字符, 如果符合条件则统计
    unsigned int count = 0; // 用来保存统计数量
    for (auto ch : text)
    {
        if (ch == U'古' || ch == U'银')
        {
            ++count;
        }
    }

    // 返回统计数量
    return count;
}

输出结果:

字符串有多少个古字和银字:6

基础讲解 2

可以看出两份代码中,unsigned int count_gu(std::u32string text);unsigned int count_guyin(std::u32string text);的函数定义除了if的判断不同,其他部分是一模一样的。既然两个函数的功能都是统计,而定义基本都是一样,那么就要考虑把它们统一成一个函数。

之前是因为值不同,所以可以用变量来作为函数参数来保存不同的值;而现在是不同的语句,可以考虑将语句写在函数里。上面说明过,函数也是一个值,不同的函数是不同的值,既然是值就可以用变量来保存。那么就可以将判断语句放到函数里,然后通过形式参数传到统计函数里。这时候就要考虑,这个用来判断的函数怎样写,同样也要考虑参数的类型是什么。

这个判断函数是用来放判断条件的。之前说过,判断就是一个运算,而运算结果是bool,那么这个判断函数的返回值就是bool。而需要判断的就是一个字符,那么形式参数的类型就是char32_t。这样,我们自己定义函数名isgu用来判断字符是不是字,定义函数名isguyin用来判断字符是不是字或者字。这两个函数的函数声明如下:

bool isgu(char32_t ch);
bool isguyin(char32_t ch);

由于它们的返回值和参数类型都是一样的,那么它们都可以用类型std::function<bool(char32_t)>声明的变量来保存,例子如下:

std::function<bool(char32_t)> isgufunc = isgu;
std::function<bool(char32_t)> isguyinfunc = isguyin;

所以可以用数据类型std::function<bool(char32_t)>来作为统计函数的参数的数据类型。

基础示例 3

那么将两个函数统一成一个函数就可以这样写:

#include <iostream> // std::cout std::endl
#include <functional> // std::function
#include <string> // std::u32string

// 以下是统计函数的使用说明
// 功能: 统计函数
// 参数: 需要被统计的字符串
// 参数: 统计函数需要的判断函数, 统计函数将会向判断函数传入每一个字符,
//       然后统计函数会根据判断函数的返回值进行统计, 如果判断函数返回
//       true, 统计函数则会处理; 如果判断函数返回false, 统计函数则忽略
// 返回值: 统计判断函数返回true的数量
unsigned int count_if(std::u32string text, std::function<bool(char32_t)> pred);

// 判断指定的UTF-32字符是不是古字
// 参数: 需要判断的字符
// 返回值: 如果指定字符是古字则返回true; 反之返回false
bool isgu(char32_t ch);

// 判断指定的UTF-32字符是不是古字或者银字
// 参数: 需要判断的字符
// 返回值: 如果指定字符是古字或者银字则返回true; 反之返回false
bool isguyin(char32_t ch);

int main(void)
{
    // 统计字符串中一共有多少个古字
    auto numofgu = count_if(U"小古银小古银我是美美哒小古银", isgu);

    // 统计字符串中一共有多少个古银这两个字
    auto numofguyin = count_if(U"小古银小古银我是美美哒小古银", isguyin);

    // 输出
    std::cout << R"raw(字符串有多少个古字:)raw" << numofgu << std::endl;
    std::cout << R"raw(字符串有多少个古字和银字:)raw" << numofguyin << std::endl;

    return 0;
}

unsigned int count_if(std::u32string text, std::function<bool(char32_t)> pred)
{
    // 遍历字符串中所有字符, 如果符合条件则统计
    unsigned int count = 0; // 用来保存统计数量
    for (auto ch : text)
    {
        if (pred(ch))
        {
            ++count;
        }
    }

    // 返回统计数量
    return count;
}

bool isgu(char32_t ch)
{
    return ch == U'古';
}

bool isguyin(char32_t ch)
{
    return ch == U'古' || ch == U'银';
}

输出结果:

字符串有多少个古字:3
字符串有多少个古字和银字:6

基础讲解 3

字符统计

先从设计函数的思维去看:函数count_if()用来统计符合条件的字符数量。然而函数count_if()只负责统计,它并不知道什么样的条件是符合的,他就把这个任务交给参数pred去负责,把每只字符都给pred()函数判断一下,只要pred()函数返回true,函数count_if()就认为是符合条件而去统计。那么函数count_if()就可以专心负责统计而不用理会细节。而参数pred就身负着判断是否符合条件的重任,它化身成为类型是std::function<bool(char32_t)>的函数,只为了完成判断每种不同条件的光荣使命。

再从调用函数的角度去玩:就是统计函数的使用说明。函数count_if()的第一个参数是需要被统计的字符串,而第二个参数是给函数count_if()判断用的,应该由调用者来定义什么字符是需要被统计的。我们需要统计有多少个字,还有需要统计一共有多少个字和字,所以就写了两个判断函数isguisguyin,供统计函数判断使用。

补充知识(了解即可)

std::function从C++11开始加入。


Comments

Make a comment

  • Index

WARNING: You are using an old browser that does not support HTML5. Please choose a modern browser (Chrome / Microsoft Edge / Firefox / Sarafi) to get a good experience.