【问题标题】:Can you start a class name with a numeric digit?你可以用数字开始一个类名吗?
【发布时间】:2013-02-23 12:18:42
【问题描述】:

C++中,类名可以以数字开头吗?例如,

template <class T> class 2DArray {

public:
    // 1D ARRAY CLASS
    class 1DArray {
    public:
        1DArray() { Create(); }
        1DArray(iterator arr) : array1d_(arr) { }
        explicit 1DArray(size_type cols, const T& t = T()) { Create(cols, t); }
        1DArray(const 1DArray& arr) { Create(arr.begin(), arr.end()); }
        1DArray& operator=(const 2DArray&);
        ~1DArray() { Uncreate(); }

        T& operator[](size_type n) {
            return array1d_[n];
        }
        const T& operator[](size_type n) const {
            return array1d_[n];
        }
}

【问题讨论】:

  • 你可能在类名的底部有数字...
  • 将其重命名为 Array,因为它默认是一维的。那么如果你有一个二维的,就叫它 Array2D。

标签: c++ class naming


【解决方案1】:

C++ 中标识符名称的规则是:

  1. 不能以数字开头
  2. 可以由字母、数字、下划线、通用字符名1实现定义字符组成
  3. 不能是keyword

C++ draft standard 中涵盖此内容的部分是 2.11标识符,其中包括以下语法:

identifier:
  identifier-nondigit            <- Can only start with a non-digit
  identifier identifier-nondigit <- Next two rules allows for subsequent 
  identifier digit               <-  characters to be those outlined in 2 above
identifier-nondigit:
  nondigit                       <- a-z, A-Z and _ 
  universal-character-name
  other implementation-defined characters
[...]

2.12关键字解释了所有保留用作关键字的标识符

最后,还保留了以下名称:

  1. 在任何范围内包含双下划线__ 或以下划线后跟大写字母(如_Apple)开头的名称,
  2. 在全局命名空间中以下划线开头的名称(如全局命名空间中的_apple)被保留。

标准草案中涵盖此内容的部分是17.6.4.3.2。我们可以从Rationale for International Standard—Programming Languages—C 中找到为什么保留这些的理由:

[...]这为编写大量幕后的非外部宏和函数提供了一个名称空间,库需要正确完成其工作[...]

C++ 中,这也适用于 name mangling,正如 example 所示。


脚注

  • 1.允许的通用字符

Annex E.1 中涵盖了允许的通用字符:

E.1 允许的字符范围 [charname.allowed]

00A8, 00AA, 00AD,

00AF、00B2-00B5、00B7-00BA、00BC-00BE、00C0-00D6、00D8-00F6、00F8-00FF

0100-167F、1681-180D、180F-1FFF 200B-200D、202A-202E、203F-2040、2054、

2060-206F 2070-218F、2460-24FF、2776-2793、2C00-2DFF、2E80-2FFF

3004-3007、3021-302F、3031-303F

3040-D7FF F900-FD3D、FD40-FDCF、

FDF0-FE44, FE47-FFFD

10000-1FFFD、20000-2FFFD、30000-3FFFD、 40000-4FFFD、50000-5FFFD、60000-6FFFD、70000-7FFFD、80000-8FFFD、 90000-9FFFD、A0000-AFFFD、B0000-BFFFD、C0000-CFFFD、D0000-DFFFD、 E0000-EFFFD

【讨论】:

  • 这对于任何类 C 语言来说都是如此,或者至少几乎是所有的。
  • 澄清:包含双下划线或下划线开头后跟大写字母,或在全局范围内以下划线开头。
  • @AthomSfere,在 C 中,不保留包含 __ 的名称,仅保留以它开始的名称。
【解决方案2】:

由于令人惊讶的是,我无法找到此问题的重复或更通用的版本,因此这里是基于标准 (C++11) 所说的答案。

首先,根据§9/1,类名是一个标识符(或者在模板特化的情况下是一个simple-template-id,但是simple-template-id 也是由 identifiers 组成)。

§2.11 定义了什么是有效的标识符。首先介绍几个基本概念:

数字是其中之一:0 1 2 3 4 5 6 7 8 9
nondigit 是其中之一:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
通用字符名\unnnn\Unnnnnnnn类型的序列(其中每个n是一个十六进制数字)

标准然后将 identifier-nondigit 定义为

  • 非数字
  • 通用字符名称
  • 或实现定义的特殊字符(&ddagger;)

最后,标识符被递归定义为

标识符
标识符-非数字
标识符 标识符-非数字
标识符数字

总结:换句话说,标识符必须以(非数字!)字母字符开头,后面可以跟任何由字母数字字符、下划线和\unnnn 类似的字符引用组成的字符。其他任何内容都是特定于实现的。


(&ddagger;) 是否支持取决于您的编译器,使用它们通常意味着您失去对其他编译器或编译器版本的可移植性。

【讨论】:

  • 感谢您的清晰总结,但我不确定为什么会令人惊讶。如果我在 Google 或 Stack Overflow 上找到答案,我就不会问了。递归的标准语言也避开了我简单的大脑。我的理解是类名是一个标识符,然后标识符 identifier-nondigit 部分对我来说毫无意义。
  • @Cindeselia 是的,当然。你问这个问题我并不感到惊讶。我很惊讶以前没有人问过这个事实。
  • @Cindeselia 哦,关于 identifier 定义:您需要阅读每一行作为替代。所以 identifier 要么是 identifier-nondigit,要么是 identifier 后跟 identifier-nondigitidentifier 后跟 数字。因此,identifier 出现在它自己的定义中,并且可以递归地替换为该定义的更多实例。您可能由此形成的任何序列都将始终以 identifier-non-digit 开头。
【解决方案3】:

简单的答案是否定的。举个例子,为什么不叫它 OneDArray?

【讨论】:

  • 这很难看,而且您正在解决错误的问题。与其将数字替换为其他数字,不如将名称更改为 Array1D
【解决方案4】:

C++ 中的名称必须以“字母”开头,其中字母全部为大写和小写“A-Z,a-z”。 '_' 也算作“字母”。然后可以在其后跟字母和数字的任意组合。

【讨论】:

  • 所以 _2DArray 应该没问题吧?
  • @Cindeselia 视情况而定,全局命名空间中以 _ 开头的任何名称都是保留的,不应使用。这个先前的线程澄清了全局 Vs。非全局命名空间,以防您不确定stackoverflow.com/questions/10269012/…
  • @Cindeselia This previous thread建议不要在名称中使用前导下划线以确保stackoverflow.com/questions/224397/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 2010-09-09
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 2016-12-21
相关资源
最近更新 更多