Object-C++关于回调的那些事

在我们学习编写程序当中 回调 是我们最常见的词语之一,回调 事件大大的增强了我们程序的逻辑性和可读性,是编程中不可缺少的魁宝。当然,我们怎么说也是学过 Object-C的人,再怎么说我们也知道在 OC 当中回调事件有代理,block 这两种惯用的模式,但是,在 C/C++ 中,我们又如何使用回调呢?使用回调又如何确保安全(当然指线程安全和防止内存泄露呢)?今天博主就带大家好好认识一番。

博主先抛砖引玉,写出两种 C/C++ 常用的回调手段,函数指针lambda 表达式

1、使用函数指针

首先我们先理解一下什么函数指针:函数指针,看名字也就知道嘛,就是指向函数的指针咯,貌似好像是废话,额,我们就实操讲解一下吧。

void function_a() {
printf("大家好,我就是一个函数");
};

// 调用
void (*f_p)() = NULL; // 一个函数指针
f_p = &function_a;
f_p();

运行上面代码,得到的 logger 为 :大家好,我就是一个函数

分析
上面代码中,我们首先定义了一个函数 void function_a() ,之后我们就能看到所谓的函数指针定义了 void (*f_p)(),很明显,它指向了函数 function_a 的地址,之后我们便能通过函数指针来直接使用函数了。

实战
那么我们该如何使用函数指针实现我们的回调呢?我们模仿工程当中使用,来为大家解决疑惑

Class CBClass {
public:
std:string m_str; 
void (*m_callback)();
}

void fun_callback(CBClass *cb){
cb->m_str = "we reset m_str";
}

// 调用
CBClass *cb_ = new CBClass();
cb->m_callback = &fun_callback;
cb->m_callback(cb);
std::cout << cb->m_str << std::endl;

运行上面程序,得到的 loggler 为: we reset m_str

这就是我们在用 C++ 面向对象的时候使用的回调,个人感觉,还是跟代理有点想得,因为你还可以设置一个 auto 的代理变量,然后直接通过函数指针调用其方法,具体怎么设计这里就不做过多的描述了,留给小伙伴们一个实践的命题吧。

2、使用 lambda 表达式

很显然, lambda 表达式 是 C++ 11 出来的产物,一部分年老的程序员还是对其抱着观望的态度,不敢贸然使用,但是,你觉我们像是年老的程序员嘛 0 0,不,我们是代码的搬运工。好吧,我们来理解什么是 lambda 表达式

auto lambda_ = [=]() {
cout << "大家好我是一个 lambda 表达式"
};

auto lambda_ = [&]() {
cout << "大家好我又是一个 lambda 表达式"
};

上面代码中使用了两种 lambda 表达式,学过 Swift 的小伙伴们都知道啥是 值类型引用类型,我们同时可以理解为 [=] 相当于 值类型 , 而 [&] 相当于引用类型。当然,也有 Object-C 的理解方法,[=] 相对与在你使用 block 中单单只是使用外部变量的值,并不关心使用变量的改变,具有使用如下

int a = 10;
void (^Callback)() = ^() {
NSLog(@"%d", a);
};

但是,如果你想要不管是 lambda内部或外部修改引用变量的值时,就要使用到 [&] ,相当于 Object-C中的 __block使用了,如下

__block int a = 10;
void (^Callback)() = ^() {
NSLog(@"%d", a);
};
a = 20;

好了,lambda表达式这么像我们的 Object-C的 block,相信大家都异常的欢喜了,但是我们在实战当中如何使用 lambda 呢?

Class CBClass {

using Callback = function<void()>;

public:
std:string m_str; 
Callback m_callback;
}

// 调用
CBClass *cb_ = new CBClass();
cb_->m_callback = [=](){
cb_->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;
delete cb_;

运行以上代码,得到的 logger 为 : we reset m_str

大家看出,lambda 的调用方式真的是跟 block像得不能再像了。

但是是什么让老一辈的 C++ 对这种新语法往而却步呢? 难道 lambda 会坑得他们变成宝字辈?
没错,lambda 也有坑。已上面 CBClass 为列子观看以下代码。

shared_ptr<CBClass> bc_ = make_shared<CBClass>();
cb_->m_callback = [=](){
cb_->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;

上面代码中,我们使用了共享指针 shared_ptr 来让 CBClass使用自动引用计数器,将内存交给系统管理,这段运行并不会崩溃,也不会报错,唯一的致命点在于内存泄露,用惯了 Object-C ARC的我们看得出,这泥马存在这循环引用呀。
我们先看看为什么会发生循环引用

发生循环引用

没错,就是这么坑爹,未使用过 C++11 特性的旧程序员们,又怎么料到这种事情呢,然后内存过多地方如此的写,程序崩溃0 0。
为了解决上面的循环引用,我们当然要将对象实现弱引用,让不让 lambda 来为我们的 cb_对象管理内存咯。

shared_ptr<CBClass> bc_ = make_shared<CBClass>();
auto weak_cb = cb_->get();
cb_->m_callback = [=](){
weak_cb->m_str = "we reset m_str";
};
cb_->m_callback();
cout << cb_->m_str << endl;

上面代码,相当于如下效果

弱引用

但是为什么上面没有使用 shared_ptr 的时候没有发生循环引用呢?大哥,我们已经手动 delete 了 cb_。


至此,博主抛砖引用的实现了两种 C/C++ 中的回调方法,接下来小伙伴们发挥自己的想象力,实现更的方式吧。

大哥,既然来了,就点个喜欢吧。

心如止水,奋力前行

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容