在最初,有C语言。在C语言中,像这样的声明是完全可能的(也确实很常见):
#include <time.h>
struct tm tm;
int stat(const char *pathname, struct stat *statbuf);
这段代码在C语言中是完全正常的,因为像“tm”或“stat”这样的标记并不代表类型。只有“struct tm”和“struct stat”才是类型。
#include <time.h>
tm my_time; // doesn't work in C
进入 C++。在 C++ 中,如果你定义了 struct tm { ... };
,那么 tm
单独就是一个类型名称。
#include <time.h>
tm my_time; // OK in C++
但是如果没有你引用中提到的“一个例外”,像上面那样的C代码将无法在C++编译器中编译。
struct tm tm; // would not compile without the exception
// because tm alone already refers to a type
// defined in this scope
由于破坏完好的C代码并不是C++的意图,因此引入了异常并加以实施。它基本上表示您可以使用与类/结构体/联合标记相同名称的变量、函数和其他一些内容进行定义。如果这样做,则该标记仅在此范围内停止成为类型名称。
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
所以这就是“类型/非类型隐藏”(因为一种类型被一个非类型隐藏)的“技巧”。它被称为“技巧”,因为它是在一个完美平稳和无聊规则(“每个名称只引用一件事情”)中轻微弯曲,使得某些事情(与旧C代码的兼容性)成为可能。正常的基于作用域的名称隐藏不是技巧。它是一件完全普通的事情,而不是任何东西的聪明弯曲。
struct vector {}; int vector = 42;
,其中两个定义在同一作用域中。 - n. m.