零零碎碎 -- 回调函数与多态
2013-03-05 15:07 robturtle 阅读(1087) 评论(0) 编辑 收藏 举报回调函数
前天写的视频播放器,第一次在编程中使用了回调函数的接口。当然,这里所说的“函数”是广义的“可调用表达式”,设计签名的时候模仿了OpenCV滚动条,最后一个参数接受void指针传入用户数据。虽然不知道他们这么设计是出于什么考虑(或者是为了兼容c代码?),不过显然在C++中有更好的方案。因为对C++的了解有限,我所能想到的比较好的设计也就是下面这两种:
- 使用 boost::any 接受用户数据
- 不接受用户数据,让用户自行绑定
boost::any 可以说就是C++版本的 void *,不过它是类型安全的。至于究竟选择上面的哪一种还是值得好好考虑一番的。首先考虑的就是,是否需要在结构中保存用户数据(值或引用),如果能够保存用户数据的话,则需要一个方法能够从外部修改它。如果是采用第二种方案的话,即使当方法不变而数据需要修改时,都需要向结构重新传入一个绑定的对象。
随后翻了一下Boost手册,倒是找到一个解决方案:使用 boost::ref 绑定对象的引用。这样的话,除非第一种方案改为使用 smart_ptr,否则还真的没什么优势。
多态
经过今天一天的实验发现,boost::any 用来做接口还可以,如果用来构建容器什么的就有点难搞,假设我要设计一个储存任何类型的容器,但容器中的部分类型有共同的几个方法,为了实现这些方法,必须在每个方法中进行类型判定。后来想到可以保存每个元素的type_info,结果发现type_info竟然是不可复制的。
唉,虽说是any类型,但真正一个容器内的元素应当都是为某个目的服务的嘛,像这种具有不同元素类型间具有共同接口的情况,还是用类继承要方便得多。
情况就是这样,现在打算用OO的方式封装OpenCV的 GUI 部分,在一个窗口类中,想设计一个成员变量保存所有窗口组件的信息。一开始本来打算用 boost:any 的方式的,结果发现要操作里面的元素实在是太麻烦了,最后选择使用类继承的方式组织所有窗口组件。学C++断断续续也快两年了,这还是第一次使用继承的特性。果不其然,对于写抽象类是非常的手生,发现要正确写好一个抽象类还有那么多条条框框,所以特地在这里写一遍虚拟类的 checklist ,以加深印象:
- 虚拟成员函数前缀 virtual, 纯虚函数后面加 "= 0“;
- 抽象类析构函数必须是virtual;
- 所有派生类务必定义析构函数(切记!),如果在连接时报错 "undefined reference 'vtable ...'“ 什么的,多半就是忘记定义派生类的析构函数了。