函数中毒在C++中是非常有用的技术.
一般来说,它指的是使函数不可用,例如,如果你想禁止在程序中使用动态分配,你可能会"毒害" malloc函数,因此无法使用它."中毒"标识符意味着"中毒"后对标识符的任何引用都是硬编译器错误
例如(在此处查看现场演示)
#include#include #pragma GCC poison malloc int main() { int* p=(int*)malloc(sizeof(int)); // compiler error use of poisoned function malloc *p=3; std::cout<<*p<<'\n'; free(p); }
我发现这种技术对于防止在C++中滥用保留字非常有用.
例如:
#include "test.h" // contains definition of some class T #pragma GCC poison private #define private public // oops compiler error use of poisoned identifier private in macro int main() { // Instantiate T & use it members }
这也可以在C中用来防止使用C++关键字,因为C++有很多关键字而不是C&C使用C++特定关键字作为C中的标识符是完全有效的.
例如(在此处查看现场演示)
#include#pragma GCC poison new int main(void) { int new=5; // oops compiler error use of poisoned identifer new. printf("%d",new); }
但是要使用这种中毒,我们需要使用实现定义的pragma指令.幸运的是,GCC pragma被clang识别并且运行良好.但是需要哪个pragma如果我有VC++编译器(Microsoft Visual studio).如何在VC++编译器中执行此操作?
MSVC++有两种方法可以做到这一点.要获得GCC版本,您可以使用#pragma deprecated.这会产生警告C4995,您可以使用/ WX将其转换为错误.
但是,这会使您指定名称的任何标识符中毒,但它没有足够的选择性来阻止碰巧具有相同标识符名称的C++成员发出警告.例如,您无法使用它来弃用特定的函数重载.通过第二种方式解决__declspec(不建议使用).
一般来说,你更喜欢后者以避免意外匹配.但要注意它有鸡和蛋的问题,你只能弃用编译器知道的函数.比如强迫你#include你根本不想使用的标题.