建议8:拒绝晦涩难懂的函数指针
在C/C++程序中,数据指针是最直接也是最常用的,理解起来也相对简单容易,但是函数指针理解起来却并不轻松。函数指针在运行时的动态调用中应用广泛,是一种常见而有效的手段。但是,如果不注重一定的使用技巧,函数指针也会变得晦涩难懂。
告诉我下面定义的含义是什么?
void (*p[10]) (void (*)()); |
如此繁琐的语法定义几乎难以辨认,这与我们提倡的可读性背道而驰了。这样的函数指针之所以让程序员发愁,最主要的原因是它的括号太多了,往往会让程序员陷在括号堆中理不清头绪。下面一层一层地来分析吧。第一个括号中的*p[10]是一个指针数组,数组中的指针指向的是一些函数,这些函数参数为void (*)(),返回值为空;参数部分的void (*)()是一个无参数、返回值为空的函数指针。
分析这样的代码简直是一种折磨。如何有效地提高函数指针定义的可读性呢?那就是使用typedef。typedef 方法可以有效地减少括号的数量,可以通过typedef来合理地简化这些声明,理清层次,所以它的使用倍受推荐。
以上面的定义为例。首先,声明一个无参数、返回空的函数指针的typedef,如下所示:
typedef void (*pfv)(); |
接下来,声明另一个typedef,一个指向参数为pfv且返回为空的函数指针:
typedef void (*pFun_taking_pfv) (pfv); |
现在,再去声明一个含有10个这样指针的数组就变得轻而易举了,而且可读性有了很大的提升:
typedef void (*pFun_taking_pfv) (pfv); |
现在,再去声明一个含有10个这样指针的数组就变得轻而易举了,而且可读性有了很大的提升:
pFun_taking_pfv p[10]; /*等同于void (*p[10]) (void (*)());*/ |
请记住:
函数指针在运行时的动态调用(例如函数回调)中应用广泛。但是直接定义复杂的函数指针会由于有太多的括号而使代码的可读性下降。使用typedef可以让函数指针更直观和易维护。拒绝晦涩难懂的函数指针定义,拒绝函数定义中成堆的括号。
建议9:防止重复包含头文件
假设,我们的工程中有如下三个文件:a.h、b.h和c.cpp,其中b文件中包含了a.h,c文件中又分别包含了a.h和b.h两个文件,如图1-1所示。
图1-1 工程文件示例
在编译整个工程时,编译器会出现“multiple definition of”错误。原因在于a.h文件被包含了两次。为了避免同一个文件被包含多次,C/C++中有两种处理方式,一种是#ifndef方式,另一种是#pragma once方式。
方式1:
|
方式2:
|