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

时间:2019-09-10 07:23:13

标签: c++

我在 cppreference 中看到了这一点。

  

在范围内查找名称会查找该名称的所有声明,但有一个例外,称为“结构hack”或“类型/非类型隐藏”:在同一范围内,可能会引用某个名称声明为class/struct/union/enum而不是typedef,而所有其他相同名称的事件都引用相同的变量,非静态数据成员(自C ++ 14起)或枚举数,或者它们都引用可能重载的函数或函数模板名称

上述文本的链接为here

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

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

2 个答案:

答案 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;
}

Show on godbolt.org

您会看到second::vectorfirst::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语言中是完全正常的,因为像tmstat这样的标签不指定类型。只有struct tmstruct 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代码兼容)无法避免。不是黑客,这是完全正常的事情,不是任何事情的巧妙转折。