在哪里声明/定义 C++ 中的类范围常量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2043493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Where to declare/define class scope constants in C++?
提问by bsruth
I'm curious about the benefits/detriments of different constant declaration and definition options in C++. For the longest time, I've just been declaring them at the top of the header file before the class definition:
我很好奇 C++ 中不同常量声明和定义选项的好处/坏处。很长一段时间,我只是在类定义之前的头文件顶部声明它们:
//.h
const int MyConst = 10;
const string MyStrConst = "String";
class MyClass {
...
};
While this pollutes the global namespace (which I know is a bad thing, but have never found a laundry list of reasons why it is bad), the constants will still be scoped to individual translation units, so files that don't include this header won't have access to these constants. But you can get name collisions if other classes define a constant of the same name, which is arguably not a bad thing as it may be a good indication of an area that could be refactored.
虽然这会污染全局命名空间(我知道这是一件坏事,但从未找到一长串为什么它不好的原因),但常量仍将范围限定为单个翻译单元,因此不包含此标头的文件将无法访问这些常量。但是如果其他类定义了一个同名的常量,你可能会遇到名称冲突,这可以说不是一件坏事,因为它可能是一个可以重构的区域的良好指示。
Recently, I decided that it would be better to declare class specific constants inside of the class definition itself:
最近,我决定最好在类定义本身内部声明类特定的常量:
//.h
class MyClass {
public:
static const int MyConst = 10;
...
private:
static const string MyStrConst;
...
};
//.cpp
const string MyClass::MyStrConst = "String";
The visibility of the constant would be adjusted depending on whether the constant is used only internally to the class or is needed for other objects that use the class. This is what I'm thinking is the best option right now, mainly because you can keep internal class constants private to the class and any other classes using the public constants would have a more detailed reference to the source of the constant (e.g. MyClass::MyConst). It also won't pollute the global namespace. Though it does have the detriment of requiring non-integral initialization in the cpp file.
常量的可见性将根据常量是仅在类内部使用还是其他使用该类的对象需要来调整。这就是我现在认为的最佳选择,主要是因为您可以将内部类常量保持为类私有,而任何其他使用公共常量的类都会对常量的来源有更详细的引用(例如 MyClass: :MyConst)。它也不会污染全局命名空间。尽管它确实具有要求在 cpp 文件中进行非整数初始化的不利影响。
I've also considered moving the constants into their own header file and wrapping them in a namespace in case some other class needs the constants, but not the whole class definition.
我还考虑将常量移动到它们自己的头文件中,并将它们包装在命名空间中,以防其他类需要常量,而不是整个类定义。
Just looking for opinions and possibly other options I hadn't considered yet.
只是在寻找我尚未考虑的意见和可能的其他选择。
回答by AnT
Your claim that declaring a non-integral constant as a static class member "have the detriment of requiring non-integral initialization in the cpp file" is not exactly solid, so to say. It does require a definition in cpp file, but it is not a "detriment", it is a matter of your intent. Namespace-level constobject in C++ has internal linkage by default, meaning that in your original variant the declaration
您声称将非整数常量声明为静态类成员“具有在 cpp 文件中要求非整数初始化的不利影响”并不完全可靠,可以这么说。它确实需要在 cpp 文件中定义,但这不是“损害”,而是您的意图。const默认情况下,C++ 中的命名空间级对象具有内部链接,这意味着在您的原始变体中,声明
const string MyStrConst = "String";
is equivalent to
相当于
static const string MyStrConst = "String";
i.e. it will define an independent MyStrConstobject in every translation unit into which this header file is included. Are you aware of this? Was this your intent or not?
即它将MyStrConst在包含此头文件的每个翻译单元中定义一个独立的对象。你知道吗?这是你的本意吗?
In any case, if you don't specificallyneed a separate object in every translation unit, the declaration of MyStrConstconstant in your original example is not a good practice. Normally, you'd only put a non-defining declaration in the header file
在任何情况下,如果不特别需要在每一个翻译单元一个单独的对象,声明MyStrConst不断在你原来的例子是不是一个好的做法。通常,您只会在头文件中放置一个非定义声明
extern const string MyStrConst;
and provide a definition in the cpp file
并在 cpp 文件中提供定义
const string MyStrConst = "String";
thus making sure that the entire program uses the same constant object. In other words, when it comes to non-integral constants, a normal practice is to define them in cpp file. So, regardless of how you declare it (in the class or out) you will normally always have to deal with the "detriment" of having to define it in cpp file. Of course, as I said above, with namespace constants you can get away with what you have in your first variant, but that would be just an example of "lazy coding".
从而确保整个程序使用相同的常量对象。换句话说,当涉及到非整数常量时,通常的做法是在 cpp 文件中定义它们。因此,无论您如何声明它(在类中或在类中),您通常都必须处理必须在 cpp 文件中定义它的“损害”。当然,正如我上面所说,使用命名空间常量,您可以摆脱第一个变体中的内容,但这只是“懒惰编码”的一个示例。
Anyway, I don't think there is a reason to over-complicate the issue: if the constant has an obvious "attachment" to the class, it should be declared as a class member.
无论如何,我认为没有理由使问题过于复杂:如果常量与类有明显的“附件”,则应将其声明为类成员。
P.S. Access specifiers (public, protected, private) don't control visibilityof the name. They only control its accessibility. The name remains visible in any case.
PS 访问说明符 ( public, protected, private) 不控制名称的可见性。他们只控制它的可访问性。该名称在任何情况下都保持可见。
回答by hjhill
Pollution of the global namespace is bad because someone (e.g. the writer of a library you use) might want to use the name MyConstfor another purpose. This can lead to severe problems (libraries that can't be used together etc.)
全局命名空间的污染很糟糕,因为有人(例如您使用的库的作者)可能想将名称MyConst用于其他目的。这可能会导致严重的问题(不能一起使用的库等)
Your second solution is clearly the best if the constants are linked to a single class. If that isn't so easy (think of physical or math constants without ties to a class in your program), the namespace solution is better than that. BTW: if you must be compatible to older C++ compilers, remember some of them can't use integral initialization in a header file - you must initialize in the C++ file or use the old enumtrick in this case.
如果常量链接到单个类,则您的第二个解决方案显然是最好的。如果这不是那么容易(想想与程序中的类没有联系的物理或数学常数),命名空间解决方案比这更好。顺便说一句:如果您必须与旧的 C++ 编译器兼容,请记住其中一些不能在头文件中使用整数初始化 -enum在这种情况下,您必须在 C++ 文件中初始化或使用旧技巧。
I think there are no better options for constants - at least can't think of one at the moment...
我认为常量没有更好的选择 - 至少目前想不出一个......
回答by James Thompson
Polluting the global namespace should be self-evidently bad. If I include a header file, I don't want to encounter or debug name collisions with constants declared in that header. These types of errors are really frustrating and sometimes hard to diagnose. For example, I once had to link against a project that had this defined in a header:
污染全局命名空间应该是不言而喻的。如果我包含一个头文件,我不想遇到或调试与该头文件中声明的常量的名称冲突。这些类型的错误确实令人沮丧,有时很难诊断。例如,我曾经不得不链接到一个在标题中定义的项目:
#define read _read
If your constants are namespace pollution, this is namespace nuclear waste. The manifestation of this was a a series of very odd compiler errors complaining about missing the _read function, but only when linking against that library. We eventually renamed the read functions to something else, which isn't difficult but should be unnecessary.
如果你的常量是命名空间污染,这就是命名空间核废料。这种情况的表现是一系列非常奇怪的编译器错误,抱怨缺少 _read 函数,但仅在链接到该库时才出现。我们最终将 read 函数重命名为其他东西,这并不难,但应该是不必要的。
Your second solution is very reasonable as it puts the variable into scope. There's no reason that this has to be associated with a class, and if I need to share constants among classes I'll declare constants in their own namespace and header file. This isn't great for compile-time, but sometimes it's necessary.
您的第二个解决方案非常合理,因为它将变量置于范围内。没有理由认为这必须与一个类相关联,如果我需要在类之间共享常量,我将在它们自己的命名空间和头文件中声明常量。这对于编译时不是很好,但有时是必要的。
I've also seen people put constants into their own class, which can be implemented as a singleton. This to me seems work without reward, the language provides you some facilities for declaring constants.
我还看到人们将常量放入他们自己的类中,该类可以作为单例来实现。这对我来说似乎没有回报,该语言为您提供了一些声明常量的设施。
回答by Chinmay Kanchi
If only one class is going to use these constants, declare them as static constinside the class body. If a bunch of related classes are going to use the constants, declare them either inside a class/struct that only holds the constants and utility methods or inside a dedicated namespace. For example,
如果只有一个类要使用这些常量,请将它们声明为static const类体内。如果一堆相关的类要使用常量,请在仅包含常量和实用程序方法的类/结构中或在专用命名空间中声明它们。例如,
namespace MyAppAudioConstants
{
//declare constants here
}
If they are constants used by the whole application (or substantial chunks of it), declare them inside a namespace in a header that is (either implicitly or explicitly) included everywhere.
如果它们是整个应用程序(或其中的大部分)使用的常量,则在头文件中的命名空间内声明它们,该头文件(隐式或显式)包含在任何地方。
namespace MyAppGlobalConstants
{
//declare constants here
}
回答by Len Holgate
Personally I use your second approach; I've used it for years, and it works well for me.
我个人使用你的第二种方法;我已经使用它多年了,它对我来说效果很好。
From a visibility point I would tend to make the private constants file level statics as nobody outside the implementation file needs to know they exist; this helps prevent chain reaction recompiles if you need to change their names or add new ones as their name scope is the same as their usage scope...
从可见性的角度来看,我倾向于制作私有常量文件级别的静态数据,因为实现文件之外的任何人都不需要知道它们的存在;如果您需要更改它们的名称或添加新名称,这有助于防止连锁反应重新编译,因为它们的名称范围与其使用范围相同...
回答by Alex Brown
You can declare them as globals in the c++ file, as long as they are not referenced in the header. Then they are private to that class and won't pollute the global namespace.
您可以在 c++ 文件中将它们声明为全局变量,只要它们未在标头中引用即可。然后它们对该类是私有的,不会污染全局命名空间。
回答by ima
don't pollute global namespace, pollute local.
不要污染全局命名空间,污染本地。
namespace Space
{
const int Pint;
class Class {};
};
But practically...
但实际上...
class Class
{
static int Bar() {return 357;}
};

