C与C++中枚举的范围

Des*_*tor 19 c c++ enums

为什么枚举值可以在用C语言定义枚举的块之外访问,而不是在C++中定义?

考虑以下C程序.

#include <stdio.h>
struct mystruct
{
    enum {INT, FLOAT, STRING} type;
    int integer;
    float floating_point;
} tu;

/* Why is INT accessible here? */
int main()
{
    tu.type = INT;
    tu.integer = 100;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它在C中编译并运行良好.

但是在C++中,它在编译时失败了.

#include <iostream>
struct mystruct
{
    enum {INT, FLOAT, STRING} type;
    int integer;
    float floating_point;
} tu;

/* Why is INT accessible here? */
int main()
{
    tu.type = INT;
    tu.integer = 100;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

[错误]未在此范围内声明'INT'

枚举和范围规则在C和C++中是不同的吗?

Ara*_*hor 24

在C中,枚举和结构的范围根本没有规则.您定义枚举的地方没有任何重要性.

在C++中,在另一个东西中定义一些东西(比如类中的枚举)使这个东西属于另一个东西.

如果你想用c ++使你的枚举全局化,你必须在你的类之外定义它,或者从你的struct路径访问它:

#include <iostream>
struct mystruct
{
    enum {INT, FLOAT, STRING} type;
    int integer;
    float floating_point;
} tu;

int main()
{
    tu.type = mystruct::INT; // INT is not in global scope, I have to precise it.
    tu.integer = 100;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意:这适用于此示例,因为您使用的structpublic默认情况下的所有内容.小心; 只有当枚举在public作用域中时,您才可以从结构或类外部访问枚举类型和值,如任何字段或函数.

  • 你对C有点太苛刻了.它肯定有名称范围,块范围如`{int i; }`.但这是功能特有的. (6认同)
  • C的问题在于它没有C++中你使用`::`运算符的任何东西的范围,因为在C中没有这样的运算符. (6认同)

Vla*_*cow 14

主要区别在于与C相反,C++有一个类范围.

在C中(6.2.1标识符的范围)

4每个其他标识符的范围由其声明的位置(在声明者或类型说明符中)确定.如果声明标识符的声明符或类型说明符出现在任何块或参数列表之外,则标识符具有文件范围,该范围终止于转换单元的末尾.

因此在这个计划中

#include <stdio.h>
struct mystruct
{
    enum {INT, FLOAT, STRING} type;
    int integer;
    float floating_point;
} tu;

/* Why is INT accessible here? */
int main()
{
    tu.type = INT;
    tu.integer = 100;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

枚举器INT,FLOAT,STRING在任何块范围之外声明,因此具有文件范围.

在C++中,定义了一个单独的范围 - 类范围:

3.3.7类范围

1以下规则描述了在类中声明的名称范围.1)在类中声明的名称的潜在范围不仅包括名称声明点后面的声明性区域,还包括所有函数体,默认参数,异常规范和非支撑或等于初始值的声明区域.该类中的静态数据成员(包括嵌套类中的这些内容).

2 集体成员的名称只能按如下方式使用:

- 在其类的范围内(如上所述)或从其类中派生的类(第10条),

- 之后 .运算符应用于其类的类型(5.2.5)的表达式或从其类派生的类,

- 在 - >运算符应用于指向其类的对象(5.2.5)或从其类派生的类的指针之后,

- :: scope resolution运算符(5.1)应用于其类的名称或从其类派生的类之后.

考虑到(9.2级成员)

1 ...类的成员是数据成员,成员函数(9.3),嵌套类型和枚举器.

因此在这个计划中

#include <iostream>
struct mystruct
{
    enum {INT, FLOAT, STRING} type;
    int integer;
    float floating_point;
} tu;

/* Why is INT accessible here? */
int main()
{
    tu.type = INT;  // Invalid access of class member
    tu.integer = 100;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

您应该通过INT以下方式之一访问类成员.

    tu.type = mystruct::INT;
Run Code Online (Sandbox Code Playgroud)

要么

    tu.type = tu.INT;
Run Code Online (Sandbox Code Playgroud)

甚至喜欢

    tu.type = ( &tu )->INT;
Run Code Online (Sandbox Code Playgroud)


PJT*_*ill 6

Vlad和Arachtor给出的答案很好,但是有一个问题他们没有解决:为什么C++以不同的方式做到这一点.如果有人熟悉Stroustrup的书,他们可能会改进这一点,但我想:

  • C很久以前就被设计为相当容易编译,而C++旨在通过使用OO使编程更可靠,其主要理想是"在一个地方,告诉用户他们需要知道使用它的所有构造,而不是更多"; 这通常是将所有属于一起的东西带来的无可比拟的好处.
  • 这导致决定使用类型定义来限制某些定义的范围,并将构造放在命名空间的层次结构中.
  • 通过限制嵌套枚举的范围,可以使用较短的名称而不会出现歧义或冲突的风险.