gpt4 book ai didi

c++ - 当我使用一个既已在类外声明又在类内声明的名称时,它是未定义的行为还是非法的?

转载 作者:行者123 更新时间:2023-12-03 06:53:39 27 4
gpt4 key购买 nike

什么时候发生:

  1. 我在全局范围内声明并定义了一个名称 X(对象或类型)。
  2. 我开始编写类(class)。在类内部,但在函数体等外部,我使用 X。
  3. 在类的后面,我再次声明姓名 X。

关于 the Class Scope page on cppreference.com ,这被认为是未定义的行为。代码片段如下所示:

typedef int c; // ::c
enum { i = 1 }; // ::i
class X {
char v[i]; // Error: at this point, i refers to ::i
// but there is also X::i
int f() {
return sizeof(c); // OK: X::c, not ::c is in scope inside a member function
}
char c; // X::c
enum { i = 2 }; // X::i
};

typedef char* T;
struct Y {
T a; // Error: at this point, T refers to ::T
// but there is also Y::T
typedef long T;
T b;
};

但在 Stanley B. Lippman 的书 Inside the C++ Object Model 的第 3.1 章中,编译器应该引发错误

他的评论:

In the following code fragment, for example, the type of length in bothmember function signatures resolves to that of the global typedef—that is, to int. When the subsequent declaration of the nested typedef of length is encountered,the Standard requires that the earlier bindings be flagged as illegal

他的代码片段是这样的:

typedef int length;
class Point3d {
public:
// oops: length resolves to global
// ok: _val resolves to Point3d::_val
void mumble( length val ) { _val = val; }
length mumble() { return _val; }

private:
// length must be seen before its first reference within the class.
// This declaration makes the prior reference illegal.
typedef float length;
length _val;
};

我用 clang 7.0.0 测试过,没有警告或错误,length 似乎绑定(bind)到 int。我知道编译器测试结果不能用于分析 UB,所以我问这个问题。

谁是对的?或者如果他们都是对的,我错过了什么?当前标准对此有何规定?

最佳答案

问题已经指向正确的 cppreference 片段 [Class Scope] :

The potential scope of a name declared in a class begins at the point of declaration and includes the rest of the class body and all function bodies ...

然后在同一个 cppreference 页面上:

If a name is used in a class body before it is declared, and another declaration for that name is in scope, the program is ill-formed, no diagnostic required.

根据上面的说法,听起来 gcc 是正确的错误并且 clang 也是正确的(因为不需要诊断)但是过于宽松允许错误的格式要编译的代码。

规范中的相关措辞[basic.scope.pdecl] 6.4.2/1 - Point of Declaration :

... The point of declaration for an enumeration is immediately after the identifier (if any) in either its enum-specifier ([dcl.enum]) or its first opaque-enum-declaration ([dcl.enum]), whichever comes first. The point of declaration of an alias or alias template immediately follows the defining-type-id to which the alias refers.

[basic.scope.declarative] 6.4.1/4.2 :

exactly one declaration shall declare a class name or enumeration name that is not a typedef name and the other declarations shall all refer to the same variable, non-static data member, or enumerator, or all refer to functions and function templates; in this case the class name or enumeration name is hidden ([basic.scope.hiding]).

然后 [basic.scope.class] 6.4.7/2 - Class scope :

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

底线:此代码格式错误(因此如果编译 can be viewed as undefined behavior ),但是编译器可以忽略它,因为不需要诊断。

关于c++ - 当我使用一个既已在类外声明又在类内声明的名称时,它是未定义的行为还是非法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64195759/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com