声明名称、引入名称和声明实体之间的区别

The difference between declaring a name, introducing a name, and declaring an entity

本文关键字:声明 之间 区别 实体      更新时间:2023-10-16

来自c++ 11标准,§7.3.3[namspace .udecl]/1:

using声明将一个名称引入using声明所在的声明区域。

using声明:

using typename optnested-name-specifier unqualified-id ;
using :: unqualified-id ;

在using声明中指定的成员名在using声明出现的声明区域中声明。

在using声明发生的声明区域中声明的名称是什么意思?

这是否意味着将该名称引入到using声明发生的声明区域?

声明名称和声明名称所表示的实体之间是否有区别?

的例子:

namespace N { static int i = 1; } /* Declares an entity denoted by 
    the name i in the declarative region of the namespace N. 
    Introduces the name into the declarative region of the namespace N.
    Declares the name i in the declarative region of the namespace N? */
using N::i; /* Declares the name i in the declarative region of the
    global namespace. Also introduces that name into the declarative
    region of the global namespace? Also declares the entity that the
    name i denotes? */ 

从第一原则来看,实体是,从[basic]

值、对象、引用、函数、枚举数、类型、类成员、位域、模板、模板特殊化、命名空间、参数包或this。[…表示实体的每个名称都由声明引入。

声明声明事物。被声明意味着它是由声明引入的,从[basic.scope.declarative]

每个名称都是在程序文本中称为声明性区域的某个部分引入的,这是最大的部分在该程序中,该名称是有效的,也就是说,该名称可以用作非限定名称指同一实体

由声明声明的名称被引入到该声明发生的作用域中,除非friend说明符的存在(11.3),详细类型说明符的某些使用(7.1.6.3),以及using-directives(7.3.4)改变这种一般行为。

这些异常在这里都不相关,因为我们讨论的是using-declarations,而不是using-directives。让我稍微修改一下您的示例,以避免使用全局命名空间:
namespace N {        //  + declarative region #1
                     //  |
    static int i;    //  | introduces a name into this region
                     //  | this declaration introduces an entity
}                    //  +

首先,N::i是在名称空间N中声明并引入N作用域的实体。现在,让我们添加一个using-declaration:

namespace B {        //  + declarative region #2
                     //  |
    using N::i;      //  | declaration introduces a name i
                     //  | but this is not an entity
}                    //  +

从[名称空间。,我们有:

如果using-declaration命名一个构造函数(3.4.3.1),它隐式地声明一组构造函数出现using声明的类(12.9);否则,使用声明在中指定的名称是同义词表示另一个命名空间或类中的一组声明。

using-declaration using N::i没有命名构造函数,所以i不是一个新的实体,而是N::i同义词

所以基本上,两个i都是在各自的名称空间中引入和声明的名称。在N中,i声明了一个具有静态链接的实体,但在B中,i声明了该实体的同义词,而不是新实体。

在声明性区域中声明的名称是什么意思using声明发生在哪里?

我将尝试用我对它的理解的一个例子来回答这个问题(参考我在描述的代码中的注释):

// "namespace X {}" introduces a declarative region of the namespace X
namespace X {
  //The name SomeObject is now introduced into the declarative region X
  // It is only visible in that declarative region
  using Y::SomeObject;
}//Declarative region X ENDS here
// SomeObject NOT visible here

下面是一个(编译器)错误的例子,它清楚地表明名字是不可见的:

#include <iostream>
namespace A
{
  struct X{};
}
namespace B
{
  struct X{};
}
namespace C
{
  using A::X;
  void foo(X){}
}
namespace D
{
  using B::X;
  void foo(X){}
}
void foo(X){} //FAILS TO COMPILE - DELIBERATE!!!
int main() 
{
    return 0;
}