我在 cppreference 中看到了这一点。
在范围内查找名称会查找该名称的所有声明,但有一个例外,称为“结构hack”或“类型/非类型隐藏”:在同一范围内,可能会引用某个名称声明为
class/struct/union/enum
而不是typedef
,而所有其他相同名称的事件都引用相同的变量,非静态数据成员(自C ++ 14起)或枚举数,或者它们都引用可能重载的函数或函数模板名称
上述文本的链接为here
我不明白什么是“结构破解”和“类型/非类型隐藏”。
它们是同一概念吗?你能给个简单的解释吗?进行摘要演示会很好。
答案 0 :(得分:8)
该句子应真正理解为:
有关名称查找的异常也涉及“结构黑客” 名为“类型/非类型隐藏”。
因此,您要寻找的概念的定义实际上是“类型/非类型隐藏”。
术语“ struct hack”可能令人困惑,因为它指的是C灵活数组,它是C特定的实现,而不是名称查找问题。
关于“类型/非类型隐藏”,它使您可以编写如下内容并进行编译:
#include <iostream>
namespace first
{
class vector
{
public:
int hidden;
};
}
namespace second {
using namespace first;
class vector
{
public:
int visible;
};
double f()
{
vector f;
f.visible=2;
int vector = f.visible;
return vector;
}
};
int main() {
std::cout << second::f() << std::endl;
}
您会看到second::vector
将first::vector
隐藏在namespace second
范围内。
此外,在f
函数int vector
中隐藏了second::vector
。
这个概念在IBM thread中得到了很好的解释:
如果类名或枚举名在范围内并且未被隐藏,则为 可见。可以通过显式隐藏类名或枚举名 具有相同名称的声明-作为对象,函数或枚举器 —在嵌套的声明性区域或派生类中。类名或 枚举名称在对象,函数或 枚举器名称可见。此过程称为名称 隐藏。
在成员函数定义中,本地名称的声明隐藏 具有相同名称的类成员的声明。的 派生类中成员的声明隐藏了 具有相同名称的基类的成员。
您还可以检查iso cpp标准:
6.3.10 Name hiding[basic.scope.hiding]或http://eel.is/c++draft/basic.scope.hiding
答案 1 :(得分:4)
一开始就有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代码兼容)无法避免。不是黑客,这是完全正常的事情,不是任何事情的巧妙转折。