命名:为什么命名常量在C ++ / Java中都是大写的?

时间:2009-05-08 09:05:21

标签: java c++ naming-conventions

我知道,对于C ++和Java来说,它是一个完善的命名约定,常量应该全部写成大写,下划线用于分隔单词。像这样(Java示例):

public final static Color BACKGROUND_COLOR = Color.WHITE;
public final static Color TEXT_COLOR = Color.BLACK;

这个命名约定很容易理解和遵循,但我问自己,为什么选择这个命名约定而不是变量的正常命名约定:

public final static Color backgroundColor = COLOR.WHITE;
public final static Color textColor = COLOR.BLACK;

Theres似乎不需要改变常量的外观。如果我们想为它们分配一个值,编译器将会阻止它。实际上它会产生问题,如果稍后将常量变为适当的变量(因为颜色可以配置为例如)。

那么将命名常量全部写成大写的最终原因是什么?历史原因?

16 个答案:

答案 0 :(得分:28)

我认为这不是技术问题,而是心理问题。命名约定不是由编译器处理(计算机并不真正关注名称),而是为正在浏览代码的程序员提供尽可能多的信息,只需要尽可能少的工作。

使用不同的命名约定清楚地告诉读者,您正在阅读的内容是在编译时固定的内容,您无需通过代码来确定值的位置和方式。

答案 1 :(得分:16)

如果我知道某事是常数,我可以多次引用它并知道它不会改变。换句话说,我知道:

Color black = Colors.BLACK;
foo(black);
foo(black);

与:

相同
foo(Colors.BLACK);
foo(Colors.BLACK);

有时候知道这很有用。我个人更喜欢.NET命名约定,即使用Pascal case来表示常量(和方法):

Foo(Colors.Black);
Foo(Colors.Black);

我不是一个狡猾的案例的忠实粉丝...但我确实认为常数显然是常数。

答案 2 :(得分:15)

我可以想象,最初,在C日,人们会使用预处理器象征性地实现“常量”:

typedef unsigned int Color;
#define BACKGROUND_COLOR 0xffffff

这样的“常数”只是美化文字,因此它们不像变量那样表现。例如,你不能接受这种“常数”的地址:

Color *p = &BACKGROUND_COLOR; // Breaks!

出于这个原因,让它们“脱颖而出”是有道理的,因为它们不仅仅是“你无法改变的变量”。

答案 3 :(得分:11)

我相信C ++这是一个从使用预处理器到#define常量值的过程。那时候,它是为了避免让预处理器在你的源代码中被践踏,因为C函数和变量名的通常约定会使它们混合大小写或小写。

从C ++的角度来看,我会说让你的常量全部大写是一个坏主意。由于这个原因,我不得不调试多个构建问题 - 请记住,C ++预处理器对命名空间和命名范围一无所知,并且很乐意替换它认为合适的内容,即使它是不合适的。

答案 4 :(得分:5)

在C(然后是C ++)中,使用预处理器#define指令定义的符号全部用大写字母写成,向开发人员发出一个响亮的信号,即代码不像它看起来那样并且不被视为正常符号。常量最初并不存在于K& R C中(虽然const稍后从C ++中恢复),因此开发人员使用#define代替,因此使用了上限。

出于某种原因,这被扭曲成Java,因为“常数是上限”,因此当前被误导(IMO)惯例。

答案 5 :(得分:3)

我认为大写常量是来自C的不良遗产。背后的逻辑与使用下划线作为私有成员的前缀时相同。这是技术性的东西,已经由private等Java关键字表示,或者在常量的情况下,static final表示。

另请参阅:http://weblogs.java.net/blog/2006/09/28/case-against-uppercases

答案 6 :(得分:2)

使用大写常量长公式更容易阅读,您不必猜测哪个元素可以变化,哪个不可以。它当然只是一个惯例,但很有帮助。

答案 7 :(得分:2)

  

不要仅仅因为常量是宏而将ALL_CAPS用于常量。

来自C ++核心指南的quote总结了所有内容。

答案 8 :(得分:1)

可能你是对的。计算机和编译器(尤其是)并不像今天那么快。

乔尔·斯波尔斯基在one of his essays中提到他对新版Turbo Pascal的编译时间印象深刻。

我记得编译不太大的程序(10-20KLOC)时在PC XT 10MHz的Turbo Pascal 5.0上覆盖大约需要20分钟......

我认为等待编译来检测错误是不可接受的。

这样的惯例有助于避免在编译中断时出现错误和浪费时间。

答案 9 :(得分:1)

这是一种解决方法,使您的开发工具无法以方便的方式识别标识符的属性。

与匈牙利符号非常相似。

当您的IDE变得更好时,您将不需要任何命名约定,但是该命令约定要求名称是关于标识符含义的全面信息。

即使这可能会发展:为什么不创建一个编程系统,你只需创建标识符,并添加属性,如“简要描述”,“类型”,...当工具到达时,可以方便地执行此操作,我在。“Intentional Programming”是一个提示。

答案 10 :(得分:1)

基本上,当人们爱上C,C ++& Java是新的还是尚未创建的,人们使用预处理器常量名称的全部大写,以表明它们实际上不是变量。

#define INT_CONST 4
#define STRING_CONST "Yello."
#define FLOAT_CONST 3.6122448

考虑到这是在C中定义一个真常量的唯一真正方法(如果你知道如何,它仍然可以改变const变量),像这样的预处理器常量只被视为常量,因此all-caps名称的含义从预处理器常量转换为简单的常量。然后将其延伸到后来的语言中,成为标准的“consts = capitals”练习。

其他语言有自己喜欢的风格,但是(例如,C#和.NET更喜欢PascalCase),所以通常最好使用首选样式(如果有的话)。

答案 11 :(得分:0)

编程时,创建人类可以理解的代码非常重要。拥有命名约定有助于实现此目的。在查看未编写的代码时,这是最好的,并且使代码更易于维护,因为它很容易区分常量和变量。

答案 12 :(得分:0)

实际上,大多数C ++命名指南(包括ISO,Boost,Sutter& Stroustrup和Google)强烈反对使用全部大写字母命名常量。这是因为宏也使用全部大写,并且它们可能在头文件中遍布,可能会产生奇怪的行为。无论如何,人们仍然使用全部大写字母,因为他们从旧的C / K& R或旧遗留代码中学习。但是,在Modern C ++新代码中,除了宏之外,你应该避免使用全部大写。

我的宠物理论为什么所有大写字母都存在,就是在非常旧的机器上,使用数字键盘直接在机器代码中输入代码。当汇编语言到达现场时,它只使用全部大写,因为那时的键盘没有标准化,而且有些键盘受到限制,例如,使用相同的数字键盘输入功能手机中的字母。然后,它被转移到许多早期语言,如BASIC,这些都是一切。当实际的终端变得可用并且键盘开始变得标准化时,人们开始使用混合的情况而没有保留,所有的大写字母都被保留用于与函数和变量相比常见的常见事件。

大多数C ++指南现在都同意使用" k"作为常量的前缀,后跟带有下划线或CamelCase的名称。我个人更喜欢kCameCase,因为它很容易区分用under_scores命名的变量。

const float kFixedRadius = 3.141;

答案 13 :(得分:0)

这纯粹是为了帮助程序员一目了然地了解他或她正在看什么。有助于知道正在使用常量以使值不会改变不管你怎么称它。

关于编译器方面的事情并非如此。命名约定纯粹是惯例,而不是真正的技术限制。

答案 14 :(得分:-1)

编码转换是为了提高可读性。你不必使用字母。例如,Java允许使用$符号。

public final static Color $$ = COLOR.WHITE;
public final static Color $_ = COLOR.BLACK;

您也可以为变量编号,但这并不意味着它是一个好主意。 ;)

答案 15 :(得分:-3)

这绝对是Java中的技术问题。考虑:

import static com.test.constants.white;
public class Foo {
  void bar(){
    //String white = "black";
    String whatAmI = white;
  }
}

取消注释上一行之前和之后“whatAmI”的值是多少?

如果常量名称与局部变量名称具有相同的约定,则会导致REAL代码问题。常量应始终具有UPPERCASE约定以避免这种情况。