"符号常量"和"魔法常量"是什么?

14
在Bjarne Stroustrup的《C++旅程》一书中,每章末尾都列出了一些建议。第一章末尾的一个建议是:

避免使用“魔法常量”,而应该使用符号常量。

什么是魔法常量和符号常量?


6
生命的意义 vs 42 - Richard Critten
1
@Richard 很好,采纳了那个。 - πάντα ῥεῖ
编程规范 101。 - Ferit
我在我的问题中找到了一个非常好的例子,看看那两个答案magic constantssymbolic constants,以及使用AddShape方法的行。 - Logman
3个回答

23
somethingElse = something * 1440;           // a magic constant
somethingElse = something * TWIPS_PER_INCH; // a symbolic one

第一个是魔术常量的示例,除了它的值以外没有传达任何其他信息。

后者更有用,因为意图是清晰的。

如果您有多个具有相同值的东西,使用符号常量也会有很大帮助:

static const int TWIPS_PER_INCH = 1440;
static const int SECTORS_PER_FLOPPY = 1440; // showing my age here :-)

这样,如果其中一个更改了,您可以轻松地确定需要更改哪个代码中的单个1440。在散布在代码中的神奇1440的情况下,您必须在多个位置进行更改并且找出哪些是twips,哪些是sectors。


1
我刚刚偶然看到了"...1440; // showing my age here :-)"。一千四百四十年 - 不可能,一千四百四十天 - 太短了。但后来我意识到:有些人甚至可能从未使用过软盘。哎呀,我也透露了我的年龄... - Scheff's Cat
1
@Scheff - 你这些年轻人和你们的时髦的3.5英寸软盘。[仿佛老人的声音]在我们那个年代,软盘是5.25英寸,每个磁道有13个扇区,35个磁道可以存储140k数据,如果不小心掉在地上还可能被椅子压坏。[仿佛老人的声音] - Scott Thompson
@ScottThompson 嗯,但3.5英寸软盘更酷。除了容量增加外,它们还有这个开关可以切换只读或非只读模式...(甚至我的一些(旧的)USB闪存驱动器也采用了这个好主意。) - Scheff's Cat

7

魔法常数是指在代码中输入的数字值,却没有解释为什么它会在那里。举个好例子比较有挑战性,但让我们试试这个:

float areaOfCircle(float radius) {
    return radius * radius * 3.14159
}

在这里我使用了一个“魔术常量”3.14159,但没有解释它的来源。更好的做法是说:

const float pi = 3.14159
float areaOfCircle(float radius) {
    return radius * radius * pi;
}

在这里,我向阅读代码的人介绍了常量的来源和使用原因,以便让其更好地理解代码... 它并非神奇地突然出现。


个人认为π不是一个好的例子,因为π实际上是一个值而不是一个名称。 - Logman
我并不反对。我很难想出一个不那么平凡的更好例子。 - Scott Thompson
更糟糕的是(我见过这种情况)355 / 113 - 直到你真正计算出它是什么,你都可以想很长时间 :-) - paxdiablo

4

魔法:

int DeepThought() { return 42; }

符号化:

const int TheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything = 42;
int DeepThought() { return TheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything; }

1
这就是关于生命、宇宙和万物的终极问题的简单答案。 - Scott Thompson
你最好将这个函数命名为theMeaningOf...,而不是更加晦涩的Q,因为它几乎有着魔数一样的问题(没有清晰地表明它应该是什么):-) - paxdiablo
@paxdiablo Q是故意模糊的,因为问题总是不确定到底是什么。除了这个"文学背景"之外,您当然是正确的。 - πάντα ῥεῖ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接