什么是“结构破解”和“类型/非类型隐藏”?

V.W*_*.Wu 11 c++

我在cppreference中看到了这一点。

在范围内查找名称会查找该名称的所有声明,只有一个例外,即“结构hack”或“类型/非类型隐藏”:在同一范围内,名称的某些出现可能引用了声明的class/struct/union/enum这不是一个typedef,而具有相同名称的所有其它出现要么全部指代相同的变量,非静态数据成员(因为C ++ 14),或枚举,或者它们都指可能过载功能或功能模板名字

上面文本的链接在这里

我不明白什么是“结构破解”和“类型/非类型隐藏”。

他们是同一概念吗?你能给个简单的解释吗?进行摘要演示会很好。

Pil*_*ili 8

该句子应真正理解为:

关于名称查找的例外涉及“结构hack”,也称为“类型/非类型隐藏”。

因此,您要寻找的概念的定义实际上是“类型/非类型隐藏”。
术语“ 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;
}
Run Code Online (Sandbox Code Playgroud)

在godbolt.org上显示

如您所见,second::vector隐藏first::vector在的范围内namespace second

而且内部f功能int vector隐藏second::vector

这个概念在IBM线程中得到了很好的解释:

如果类名或枚举名在范围内且未隐藏,则可见。可以通过在嵌套的声明性区域或派生类中使用与对象,函数或枚举器相同的名称进行显式声明来隐藏类名称或枚举名称。在对象,函数或枚举器名称可见的任何位置,类名称或枚举名称都是隐藏的。此过程称为名称隐藏。

在成员函数定义中,本地名称的声明隐藏具有相同名称的类成员的声明。派生类中成员的声明隐藏了同名基类成员的声明。

您还可以检查iso cpp标准:
6.3.10名称隐藏[basic.scope.hiding]http://eel.is/c++draft/basic.scope.hiding

  • 范围和名称空间与问题的主题无关。类型/非类型隐藏指的是这个序列:`struct vector {}; int vector = 42;` 其中两个定义**在同一范围内**。 (2认同)

n. *_* m. 6

一开始,有 C。在 C 中,像这样的声明是完全可能的(而且确实很频繁):

#include <time.h>  // defines struct tm { ... }
struct tm tm;

int stat(const char *pathname, struct stat *statbuf); // defined somewhere in POSIX headers
Run Code Online (Sandbox Code Playgroud)

这段代码在 C 中是完全正常的,因为标签喜欢tmstat不指定类型。只有struct tmstruct stat这样做。

#include <time.h> 
tm my_time; // doesn't work in C
Run Code Online (Sandbox Code Playgroud)

输入 C++。在 C++ 中,如果您定义,struct tm { ... };tm 只有一个类型名称。

#include <time.h>
tm my_time; // OK in C++
Run Code Online (Sandbox Code Playgroud)

但是,如果没有引用中详述的“一个例外”,则上述 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
Run Code Online (Sandbox Code Playgroud)

由于破坏完美的 C 代码不是 C++ 的意图,因此发明并实施了异常。它基本上是说你可以定义变量、函数和其他一些与 class/struct/union 标签同名的东西。如果你这样做了,那么标签本身就不再是这个范围内的类型名称。

#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
Run Code Online (Sandbox Code Playgroud)

所以这就是“类型/非类型隐藏”(因为一个类型被一个非类型隐藏)” hack。它被称为hack是因为它在其他完全平滑和无聊的规则中略微弯曲(“每个名称都指一件事和一件事”),这允许一些(与旧的 C 代码的兼容性),如果没有的话,这是不可能的。正常的基于范围的名称隐藏不是黑客攻击。这是一个完全常规的事情,而不是巧妙的弯曲任何事物。