0. 问题的引入
一直觉得我的3DLIB里面的.h文件的这段代码很别扭:
namespace _CPPYIN_3DLib { // 全局变量 static IDirect3DDevice9* pDevice = 0; static IDirect3DSurface9* pSurface = 0; static D3DLOCKED_RECT lockedRect; // 函数声明 bool Init3DLib(HINSTANCE hInstance, HWND hWnd, int width, int height); int LockSurface(); int UnlockSurface(); int DrawPixel(int x, int y, DWORD color); int DrawLine(int x0, int y0, int x1, int y1, DWORD color); int ClipLineByRect(int x1, int y1, int x2, int y2, RECT rect, int &nx1, int &ny1, int &nx2, int &ny2); // 返回1则有交点,返回0则无交点 void FlipSurface(); void Release3DLib(); }
别扭在全局变量的定义这里。
我希望所有#include这个头文件的程序,能够访问这3个全局变量。但如果不加上static就会出现重复定义的情况。
其实大家都知道另外一个方法也可以解决,就是把他们定义在.cpp文件里,而在.h里面放上extern前缀做他们的声明。
但是我就是爱钻死牛角尖,这两种方式到底哪种好呢?于是我又翻了几本书,把连接器相关的知识又复习了一遍,其中TCPL中说了这么一句话:“在C/C++程序里,关键字static也被(混乱的)用于表示使用内部连接。请不要使用static,除了在函数和类的内部”。
作者对于static来表示内部连接的做法是极其反对的,这也引来了我对“贬斥特征”的学习。
1. 什么是贬斥特征?
C++标准化委员会通过“贬斥某个特征”表达了他们的一种期望——这个特征应该靠边站。虽然某些特征是多余或极其危险的,委员会也无权去删除C中已有的特征。那么他们只有“贬斥”他们,并用态度来表明,程序员绝对不应该使用他们。
上面static的用法,就是被贬斥的一种之一。
2. 一些被贬斥特征的实例
1) C++贬斥用static表示“局部编译单位”的用法,用无名命名空间来替代。
2) 隐式地将字符串字面量转换到非const的char*也受到贬斥。
3) 对C风格的强制转换是贬斥态度,在所有需要转换类型的地方,都应该使用static_cast、reinterpret_cast、const_cast或者他们的组合。
3. 总结
我们的代码里一定存在string str = "somestr";我们的代码里一定有int i = int(1.2 + 3);可能是我们觉得没有必要,可能是我们实在懒的去写static_cast,也许我们不曾因为这些简陋的写法而陷入过重大的代码危机。但从现在,我打算改正这些,让这些东西在我的代码库中永远消失,不是因为别的,只为表明一个态度,我对我自己的作品与代码如同我的孩子,我会高质量、精心的照顾他们。