Point 6
位运算
我们都很清楚,位运算涉及到数据的二进制表示,以及数据的大小或者说长度。在进行位移操作的时候我们不得不关注变量的长度,因为一般的位移操作(>>或<<)并不是循环位移,有移出数据位的可能,除非我们期望得到那种结果。考虑下面例子:
int x = 1; x >>= 1; x = ?
结果x = 0。其它的<<,^,~等位运算具体细节请参考《The C Programming Language》或者数据的补码表示。下面我主要介绍与类型定义有关的位运算。
考虑下面的例子:
typedef unsigned int FIND_T;
#define FIND_ARG_NO_ATTR 0x0000
#define FIND_ARG_PATH 0x0001
#define FIND_ARG_TYPE 0x0002
#define FIND_ARG_PATH_TYPE 0x0003
#define FIND_ARG_FILENAME 0x0004
#define FIND_ARG_PATH_FILENAME 0x0005
#define FIND_ARG_FILENAME_TYPE 0x0006
#define FIND_ARG_ALL 0x0007
#define FIND_ARG_BAD 0x0008
这些宏定义为查找操作的属性参数。正如你所看到的,
FIND_ARG_PATH
定义为十六进制数
0x0001
,它代表以路径方式查找。同样定义
FIND_ARG_TYPE
,当需要
FIND_ARG_PATH_TYPE
属性的时候,可以直接使用该宏,或者使用
FIND_ARG_PATH | FIND_ARG_TYPE
的组合,显然这两种方式的结果(
0x0003
)是一样的。这样用的好处在于我们能从基本的属性组合出复杂的属性,也方便从复杂的属性中提取基本属性。看下面例子:
FIND_T find = FIND_ARG_PATH_TYPE;
if ( find & FIND_ARG_PATH )
{
//if statement, deal with path
}
这种应用要求从
BCD
二进制到十六进制或十进制的考虑。在设计这种类型宏的时候尽量从
BCD
二进制开始,然后转换为十六进制或十进制,以期得到较合理的结果。
Point 7
虚成员函数
考虑下面的例子:
class CSA :
public Counter,
public LIB,
public CmdParser,
public Help
{
void Print(PITEM pItm) const;
//basic interfaces and data of class CSA
};
class LIB
{
virtual void Print(PITEM pItm) const;
// basic interfaces and data of class LIB
}
类CSA继承了类LIB。假如有一函数:
void CSA::Fun()
{
This->Print(pItm);
//body of Fun
}
结果将得到一个警告。因为编译器搞不清楚到底调用的是哪个
Print()
。
指出函数的域会好些:
LIB::Print(pItm)
。