一开始有 C。在 C 中,这样的声明是完全可能的(而且确实很常见):
#include <time.h> // defines struct tm { ... }
struct tm tm;
int stat(const char *pathname, struct stat *statbuf); // defined somewhere in POSIX headers
这段代码在 C 语言中是完全正常的,因为像tm 或stat 这样的标签 不指定类型。只有struct tm 和struct stat 可以。
#include <time.h>
tm my_time; // doesn't work in C
输入 C++。在 C++ 中,如果您定义 struct tm { ... };,则 tm alone 是一个类型名称。
#include <time.h>
tm my_time; // OK in C++
但是如果没有您引用中详述的“一个例外”,上面的 C 代码将无法使用 C++ 编译器进行编译。
#include <time.h>
struct tm tm; // would not compile without the exception
// because tm alone already refers to a type
// defined in this scope
由于破坏完美的 C 代码并不是 C++ 的本意,因此发明并实施了异常。它基本上说你可以定义变量、函数和其他一些与类/结构/联合标签同名的东西。如果你这样做了,那么标签本身就不再是这个范围内的类型名称。
#include <time.h>
struct tm tm; // compiles because of the exception
tm my_time; // no longer compiles because `tm` variable hides the type
struct tm my_time; // OK
所以这就是“类型/非类型隐藏”(因为类型被非类型隐藏)”hack。它被称为 hack,因为它是对原本完全平滑和无聊的规则的轻微弯曲(“每个名称仅指一件事和一件事”),它允许一些事情(与旧 C 代码的兼容性),如果没有这些事情是不可能的。正常的基于范围的名称隐藏不是 hack。这是完全正常的事情,而不是任何巧妙的弯曲。