1.小试牛刀
#include <iostream>
using namespace std;
#include <memory>
#include <stdlib.h>
int add(int a, int b) {
return a + b;
}
void test01() {
// 函数指针可以指向任何类型的函数,只要函数的参数列表和返回值类型匹配即可
int (*pFunc)(int,int) = add;
// 函数指针可以像普通函数一样被调用,通过函数指针变量名加上括号的方式
int result = (*pFunc)(1,2);
cout << result << endl; // 输出 3
}
// typedef 返回类型(*新的函数名)(参数列表)
typedef int (*INT_func)(int,int);
void test02() {
INT_func pFunc = add;
int result = pFunc(2,3);
cout << result << endl; // 输出 5
}
// 回调函数,它允许一个函数作为参数传递给另一个函数
// 这种特性使得我们可以将一些特定的任务委托给其他函数来完成
// 定义一个函数指针类型
typedef void(*Callback)(int);
// 定义一个函数,该函数接受一个回调函数作为参数
void doSomething(Callback callback) {
cout<<"Doing something..."<<endl;
// 调用回调函数
int data = 1024;
callback(data);
}
// 定义一个回调函数
void printMyData(int data) {
cout<<"My data is: "<<data<<endl;
}
int main() {
test01();
test02();
// 将回调函数传递给doSomething函数
/*
doSomething函数接受一个Callback类型的参数,这是
一个指向函数的指针.doSomethings函数调用这个回调函数,
并且将一个整型变量作为参数传递给它
printMyData在此是一个简单的回调函数,它接受一个整型变量作为
参数并且把它打印出来
*/
doSomething(printMyData);
return 0;
}
PS D:\Work\c++> ./bin/app
3
5
Doing something...
My data is: 1024
PS D:\Work\c++>
2.动态函数指针
在学习这个知识点的时候,我遇到的坑,非常感谢这位大佬给我指点迷津:
动态函数指针free报错_编程语言-CSDN问答https://ask.csdn.net/questions/8061857?spm=1001.2014.3001.5505
#include <iostream>
using namespace std;
#include <memory>
#include <stdlib.h>
int add(int a, int b) {
return a + b;
}
/*
动态函数指针是指在运行时根据需要动态分配和修改的函数指针
它可以在程序运行时根据需要指向不同的函数,从而实现更加灵活
和动态的函数调用
在c++中,可以使用动态内存分配函数(如malloc或new)来创建
动态函数指针
*/
int test01() {
// 创建一个指向函数的指针
int(**pFunc)(int, int);
// 使用malloc动态分配内存
int size = sizeof(int(*)(int, int));
pFunc = (int(**)(int, int))malloc(size);
// 将函数指针指向 add函数
*pFunc = add;
// 调用函数
int result = (*pFunc)(2, 3);
cout << result << endl; // 输出 5
// 释放内存
free(pFunc);
return 0;
}
int main() {
test01();
return 0;
}
打印结果:
PS D:\Work\c++> ./bin/app
5
PS D:\Work\c++>
3.异步编程
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
// A的实现,一般会隐藏
typedef void (*CallbackPtr)(int);// 函数指针定义
typedef struct dataCB{
int data;
CallbackPtr callback;
}dataCB;
// 创建实例
dataCB dataCBInstance = {0, NULL};
void* callback_thread(void* arg) { // 此处用的是一个线程
// 循环改变p->a的值为 0 1 2 3 4 5 6 7 8 9,每个3s改变一次
dataCB* p = (dataCB*)arg;
while (1) {
sleep(3);// 延时3s执行callback函数
p->callback(p->data);// 函数指针执行函数,这个函数来自于应用层B
p->data = (p->data + 1) % 10;
}
}
void startup_app_A() {
// 创建线程
pthread_t tid;
pthread_create(&tid, NULL, callback_thread, (void*)&dataCBInstance);
}
// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr cb) {
printf("SetCallBackFun print! \n");
dataCBInstance.callback = cb;
}
// //-----------------------应用者B-------------------------------
void recieve(int data) // 应用者增加的函数,此函数会在A中被执行
{
//do something
printf("B得到A的数据 = %d\n",data);
}
int main(void) {
// 启动A
startup_app_A();
SetCallBackFun(recieve);
// 主函数
while (1) {
// std::cout << "main function" << std::endl;
printf("main function\n");
sleep(2);
}
return 0;
}
PS D:\Work\c++> ./bin/app
SetCallBackFun print!
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
二、C++回调函数
1.动态函数指针
#include <iostream>
using namespace std;
#include <memory>
#include <stdlib.h>
int add(int a, int b) {
return a + b;
}
/*
动态函数指针是指在运行时根据需要动态分配和修改的函数指针
它可以在程序运行时根据需要指向不同的函数,从而实现更加灵活
和动态的函数调用
在c++中,可以使用动态内存分配函数(如malloc或new)来创建
动态函数指针
*/
typedef int(*handleFunc)(int,int);
int test01() {
// 创建一个指向函数的指针
int(**pFunc)(int, int);
pFunc = new handleFunc;
// 将函数指针指向 add函数
*pFunc = add;
// 调用函数
int result = (*pFunc)(2, 3);
cout << result << endl; // 输出 5
// 释放内存
delete pFunc;
pFunc = nullptr;
return 0;
}
int main() {
test01();
return 0;
}
2.简单回调
#include <iostream>
#include <functional>
// 定义一个回调函数类型
typedef std::function<void(int)> Callback;
// 定义一个接受回调函数的函数
void process(int value,Callback callback) {
std::cout<<"传入处理值: "<<value<<std::endl;
callback(value); // 调用回调函数
}
// 定义一个回调函数
int add(int value) {
value += 10;
std::cout<<"传出结果值: "<<value<<std::endl;
return value;
}
int main() {
int value = 42;
process(value,add); // 传递回调函数给process函数
return 0;
}
执行结果:
PS D:\Work\c++> ./bin/app
传入处理值: 42
传出结果值: 52
PS D:\Work\c++>
3.使用包装器function
(1) 可调用对象
// 可调用对象
/*
在C++中,可以像函数一样的调用的有:普通函数,
类的静态成员函数、仿函数、lambda函数,类的
非静态成员函数、可被转换为函数的类的对象,
统称可调用对象或函数对象
可调用对象有类型,可以用指针存储它们的地址,可以
被引用(类的成员函数除外)
*/
#include <iostream>
using namespace std;
class Object {
public:
// 仿函数
void operator()(int age, string name) {
cout << "年龄:" << age << ",姓名:" << name << endl;
}
// 类的非静态成员函数
void show(int age, string name) {
cout << "年龄:" << age << ",姓名:" << name << endl;
}
};
// 仿函数
void test01() {
Object obj;
obj(20, "呵呵哒");
Object& objRef = obj; // 引用函数
objRef(18, "小比尔");
}
// lambda函数
void test02() {
auto func = [](int age, string name) {
cout << "年龄:" << age << ",姓名:" << name << endl;
};
func(20, "heheda");
auto& funcRef = func;// 引用lambda对象
funcRef(23, "小比尔");
}
// 类的非静态成员函数有地址,但是只能通过类的对象才能调用它,
// C++对它做了特别处理,类的非静态成员函数只有指针类型,
// 没有引用类型,不能引用
void test03() {
Object obj;
obj.show(30, "智慧老人");
void(Object:: *pobj)(int, string) = &Object::show; // 定义类的成员函数的指针
(obj.*pobj)(20, "呵呵哒");
using PFun = void(Object::*)(int, string);
PFun pShow = &Object::show;
(obj.*pShow)(78, "圣诞老人");
}
int main() {
test03();
return 0;
}
(2)C++之可调用对象,bind绑定器和function包装器
// 包装器function
// 包含头文件:#include <functional>
// std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;
#include <iostream>
#include <functional>
#include <string>
using namespace std;
enum OP {
ADD,
MUL,
SUB
};
int add(int a, int b) {
return a + b;
}
using handleFunc = function<int(int, int)>;
class Object {
public:
int add(int a, int b) {
return a + b;
}
static int sub(int a, int b) {
return a - b;
}
static int mul(int a, int b) {
return a * b;
}
// 仿函数
int operator()(int a, int b, handleFunc cb, OP op) {
switch (op) {
case ADD:
cout << "("<< a << "+" << b << ") = ";
break;
case MUL:
cout << "(" << a << "*" << b << ") = ";
break;
case SUB:
cout << "(" << a << "-" << b << ") = ";
break;
}
cout << cb(a, b) << endl;
return cb(a, b);
}
};
void test01() {
Object obj;
function<int(int, int)> func = add;
cout << func(1, 2) << endl;
}
void test02() {
Object obj;
handleFunc addCB = std::bind(&Object::add, &obj, std::placeholders::_1, std::placeholders::_2);
cout << "addCB(1, 2): " << addCB(1, 2) << endl;
handleFunc subCB = Object::sub;
cout << "subCB(9, 3): " << subCB(9, 3) << endl;
subCB = obj.mul;
cout << "subCB(10, 6): " << subCB(10, 6) << endl;
handleFunc mulCB = Object::mul;
cout << "mulCB(3, 3): " << subCB(3, 3) << endl;
subCB = obj.mul;
cout << "mulCB(2, 6): " << subCB(2, 6) << endl;
function<int(int, int, handleFunc, OP)> operCB = obj;
operCB(2, 3, add, ADD);
operCB(4, 1, obj.sub, SUB);
operCB(2, 9, obj.mul, MUL);
}
int main() {
//test01();
test02();
return 0;
}
#include <iostream>
#include <functional>
using namespace std;
using handleFunc = function<void()>;
class Object {
public:
// 构造函数参数是一个包装器对象
Object(const handleFunc& f) :m_callback(f) {}
void notify() {
m_callback();// 调用通过构造函数得到的函数指针
}
private:
handleFunc m_callback;
};
class Subject{
public:
void operator()() { cout << "heheda" << endl; }
};
int main() {
Subject s;
Object obj(s);
obj.notify();
return 0;
}
#include <iostream>
#include <functional>
using namespace std;
class Person {
public:
// 仿函数
void operator()(int age, string name) {
cout << "age: " << age << ",name: " << name << endl;
}
void show(int age, string name) {
cout << "age: " << age << ",name: " << name << endl;
}
};
void test01() {
Person person;
// 仿函数
function<void(int, string)> opFunc = bind(Person(), placeholders::_1, placeholders::_2);
opFunc(20,"heheda");
// 类成员函数需要绑定该类的this指针
Person p1;
function<void(Person&, int, string)> showFunc =
bind(&Person::show,placeholders::_1, placeholders::_2, placeholders::_3);
showFunc(p1, 17, "Tom");
// 为了统一,将对象提前绑定
function<void(int, string)> showFunc2 =
bind(&Person::show, p1, placeholders::_1, placeholders::_2);
showFunc2(8, "Jerry");
}
int main() {
test01();
}
#include <iostream>
#include <functional>
#include <thread>
#include <unistd.h>
using namespace std;
// A的实现,一般会隐藏
using CallbackPtr = std::function<void(int)>;
typedef struct dataCB{
int data;
CallbackPtr callback;
}dataCB;
// 创建实例
dataCB dataCBInstance = {0, NULL};
void* callback_thread(void* arg) { // 此处用的是一个线程
// 循环改变p->a的值为 0 1 2 3 4 5 6 7 8 9,每个3s改变一次
dataCB* p = (dataCB*)arg;
while (1) {
sleep(3);// 延时3s执行callback函数
p->callback(p->data);// 函数指针执行函数,这个函数来自于应用层B
p->data = (p->data + 1) % 10;
}
}
void startup_app_A() {
// 创建线程
std::thread(callback_thread, (void*)&dataCBInstance).detach(); // .detach()分离线程
}
// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr cb) {
printf("SetCallBackFun print! \n");
dataCBInstance.callback = cb;
}
// //-----------------------应用者B-------------------------------
void recieve(int data) // 应用者增加的函数,此函数会在A中被执行
{
//do something
printf("B得到A的数据 = %d\n",data);
}
int main(void) {
// 启动A
startup_app_A();
SetCallBackFun(recieve);
// 主函数
while (1) {
printf("main function\n");
sleep(2);
}
return 0;
}
(3)异步编程
#include <iostream>
#include <functional>
#include <thread>
#include <unistd.h>
using namespace std;
// A的实现,一般会隐藏
using CallbackPtr = std::function<void(int)>;
typedef struct dataCB{
int data;
CallbackPtr callback;
}dataCB;
// 创建实例
dataCB dataCBInstance = {0, NULL};
void* callback_thread(void* arg) { // 此处用的是一个线程
// 循环改变p->a的值为 0 1 2 3 4 5 6 7 8 9,每个3s改变一次
dataCB* p = (dataCB*)arg;
while (1) {
sleep(3);// 延时3s执行callback函数
p->callback(p->data);// 函数指针执行函数,这个函数来自于应用层B
p->data = (p->data + 1) % 10;
}
}
void startup_app_A() {
// 创建线程
std::thread(callback_thread, (void*)&dataCBInstance).detach(); // .detach()分离线程
}
// 给B的接口,接收注册函数
extern void SetCallBackFun(CallbackPtr cb) {
printf("SetCallBackFun print! \n");
dataCBInstance.callback = cb;
}
// //-----------------------应用者B-------------------------------
void recieve(int data) // 应用者增加的函数,此函数会在A中被执行
{
//do something
printf("B得到A的数据 = %d\n",data);
}
int main(void) {
// 启动A
startup_app_A();
SetCallBackFun(recieve);
// 主函数
while (1) {
printf("main function\n");
sleep(2);
}
return 0;
}
PS D:\Work\c++> ./bin/app
SetCallBackFun print!
main function
main function
B得到A的数据 = 0
main function
main function
B得到A的数据 = 1
main function
B得到A的数据 = 2
main function
main function
B得到A的数据 = 3
main function
B得到A的数据 = 4
main function
main function
B得到A的数据 = 5
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
PS D:\Work\c++> cmake --build build
[100%] Built target app
PS D:\Work\c++> ./bin/app
SetCallBackFun print!
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
main function
B得到A的数据 = 5
main function
B得到A的数据 = 6
main function
main function
B得到A的数据 = 7
main function
B得到A的数据 = 8
main function
main function
B得到A的数据 = 9
main function
B得到A的数据 = 0
main function
main function
B得到A的数据 = 1
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
main function
B得到A的数据 = 9
main function
main function
B得到A的数据 = 0
main function
B得到A的数据 = 1
main function
main function
B得到A的数据 = 2
main function
B得到A的数据 = 3
main function
main function
B得到A的数据 = 4
main function
B得到A的数据 = 5
main function
main function
B得到A的数据 = 6
main function
B得到A的数据 = 7
main function
main function
B得到A的数据 = 8
参考文章:
未完待续 ~
文章浏览阅读1.2w次,点赞2次,收藏12次。安装ssms的时候卡在界面看官方ssms的安装教程,发现Micros Visual Studio Tools for Applicantions 2017是ssms下载的时候配套的库,应该是安装的时候卡在Micros Visual Studio Tools for Applicantions 2017的安装上面,所以决定从官方手动下载这个工具库。您尝试安装的产品版本比此计算机上已经安装的版本低,分析应该是我下载的Visual studio 2022版本过高,不支持下载mvs .._ssms安装卡住
文章浏览阅读206次。项目运行环境配置:Pychram社区版+ python3.7.7 + Mysql5.7 + HBuilderX+list pip+Navicat11+Django+nodejs。项目技术:django + python+ Vue 等等组成,B/S模式 +pychram管理等等。环境需要1.运行环境:最好是python3.7.7,我们在这个版本上开发的。其他版本理论上也可以。2.pycharm环境:pycharm都可以。推荐pycharm社区版;_分销系统开源 python
文章浏览阅读230次。Docker启动时报错:We could not resolve DockerHub using DNS.解决方法:依次检查Firewalld、NetWorkManager、selinux的状态,并关闭关闭Firewalldsystemctl status firewalldsystemctl stop firewalldsystemctl disable firewalld..._unable to retrieve dockerhub
文章浏览阅读79次。题目链接:https://vjudge.net/problem/LightOJ-12131213 - Fantasy of a SummationPDF (English)StatisticsForumTime Limit:2 second(s)Memory Limit:32 MB...
文章浏览阅读4.1k次。swiper 前进后退按钮的显示和隐藏鼠标进入和离开时,前进后退按钮显示和隐藏<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://unpk_swiper隐藏箭头显示
文章浏览阅读3k次。字符串Go语言中的字符串是通过UTF-8编码,字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符 。字符串底层结构是一个起始地址和长度(字节个数)字符串转义符Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等转义符含义/r回车符/n换行符/t制表符/’单引号/"双引号//反斜杠例如://打印一个Windows平台下的一个文件路径package mainimport ( "_go .new.string(
文章浏览阅读2.1k次,点赞4次,收藏6次。自然常数小趣事宇宙第一公式:欧拉公式伯努利微积分_数学之美 常数e
文章浏览阅读1.2w次,点赞30次,收藏363次。记录下201电赛F题的openmv 和 K210巡线吧,当时是借鉴了网上有个老哥的想法,也找不到是那个老哥了,抱歉了。本人菜鸟一枚,大佬们有不对的地方请指出。_k210 vs openmv
文章浏览阅读2.8k次。#include #include #include #include #include #include #include #define GETADR(n,str) (str *) calloc (n,sizeof(str)) // 申请N个指定字符串长度的地址#define W16 16 #define C16 32 unsigned char bi
文章浏览阅读410次,点赞4次,收藏6次。上面这些公司都是时下最受欢迎的互联网大厂,他们的职级、薪资、福利也都讲的差不多了,相信大家都是有梦想和野心的人,心里多少应该都有些想法。也相信很多人也都在为即将到来的金九银十做准备,也有不少人的目标都是这些公司。我这边有不少朋友都在这些厂工作,其中也有很多人担任过面试官,上面的资料也差不多都是从朋友那边打探来的。除了上面的信息,我这边还有这些大厂近年来的面试真题及解析,以及一些朋友出于兴趣和热爱一起整理的Android时下热门知识点的学习资料。
文章浏览阅读114次。原文:C# “贝格尔”编排法采用“贝格尔”编排法,编排时如果参赛队为双数时,把参赛队数分一半(参赛队为单数时,最后以“0”表示形成双数),前一半由1号开始,自上而下写在左边;后一半的数自下而上写在右边,然后用横线把相对的号数连接起来。这即是第一轮的比赛。第二轮将第一轮右上角的编号(“0”或最大的一个代号数)移到左角上,三轮又移到右角上,以此类推。即单..._c# 贝格尔编排算法
文章浏览阅读286次。静态网站的编写主要是用 HTML DⅣV+ CSSJS等来完成页面的排版设计,一般的网页作业需要融入以下知识点:div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉导航栏、鼠标划过效果等知识点,学生网页作业源码,制作水平和原创度都适合学习或交作业用,记得点赞。 精彩专栏推荐 【作者主页——获取更多优质源码】 【web前端期末大作业——毕设项目精品实战案例(1000套)】 旅游景_北京理工大学首页设计源码