Where to declare/define class scope constants in C++? - c++

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:
//.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.
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.

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 const object in C++ has internal linkage by default, meaning that in your original variant the declaration
const string MyStrConst = "String";
is equivalent to
static const string MyStrConst = "String";
i.e. it will define an independent MyStrConst object in every translation unit into which this header file is included. Are you aware of this? Was this your intent or not?
In any case, if you don't specifically need a separate object in every translation unit, the declaration of MyStrConst constant in your original example is not a good practice. Normally, you'd only put a non-defining declaration in the header file
extern const string MyStrConst;
and provide a definition in the cpp file
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".
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 visibility of the name. They only control its accessibility. The name remains visible in any case.

Pollution of the global namespace is bad because someone (e.g. the writer of a library you use) might want to use the name MyConst for another purpose. This can lead to severe problems (libraries that can't be used together etc.)
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 enum trick in this case.
I think there are no better options for constants - at least can't think of one at the moment...

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.
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.

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.

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...

If only one class is going to use these constants, declare them as static const inside 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,
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
}

don't pollute global namespace, pollute local.
namespace Space
{
const int Pint;
class Class {};
};
But practically...
class Class
{
static int Bar() {return 357;}
};

Related

How can I prevent static class member variables from needing two definitions/declarations?

I don't think this is a duplicate because other questions ask why it's necessary, not how I can avoid writing it twice.
Often with classes I'll introduce member variables and then, for whatever reason, remove them shortly after if I don't like them.
With a non-static member variable I can simply add a member to the header file and use it in my code immediately. With a static member variable I have to do the following:
Add the new member to the class definition, e.g. static int a;.
Copy the new member declaration.
Go to a .cpp file (any .cpp file will do if I understand right).
Paste the variable in the file.
Remove the static keyword.
Add the class namespace/scope after the type and before the variable name.
All of this makes me want to just make all of my classes instantiable and do everything through an object, even if it wouldn't make sense.
So even if this is just a requirement of the language and there is no way around it, is there a way to cut back on the repetition by using macros in some way?
Also I was thinking if maybe it mightn't be simpler to just have one .cpp file containing all of these static member variable definitions. Seeing as though (I've heard) static member variables are basically global variables accessed through a class namespace, is this a better idea than doing it in each corresponding .cpp file?
I'm going to provide a solution for integral types (since you highlight those types in your question):
struct Foo
{
enum {Value = 123;}
};
Value can be used as an integral constant, is the same for all instances of Foo (rather like a static) and does not require definition in a source file. Note though that &Value makes no sense, i.e. there's no such thing as a pointer to an enumeration value.
You can do things with constexpr in later C++ standards (C++11 onwards), but my way is arguably simpler and is also an important metaprogramming technique.
(If this is not sufficient for what you want then please downvote and I'll remove.)
A possibility is too use static in function scope, something like:
struct C {
static int& a() {
static int a_instance = 42;
return a_instance;
}
};

Declaring static data members of normal class and class template

I read the reason for defining static data members in the source file is because if they were in the header file and multiple source files included the header file- the definitions would get output multiple times. I can see why this would be a problem for the static const data member, but why is this a problem for the static data member?
I'm not too sure I fully understand why there is a problem if the definition is written in the header file...
The multiple definition problem for variables is due to two main deficiencies in the language definition.
As shown below you can easily work around it. There is no technical reason why there is no direct support. It has to do with the feature not being in sufficient high demand that people on the committee have chosen to make it a priority.
First, why multiple definitions in general are a problem. Since C++ lacks support for separately compiled modules (deficiency #1), programmers have to emulate that feature by using textual preprocessing etc. And then it's easy to inadvertently introduce two or more definitions of the same name, which would most likely be in error.
For functions this was solved by the inline keyword and property. A freestanding function can only be explicitly inline, while a member function can be implicitly inline by being defined in the class definition. Either way, if a function is inline then it can be defined in multiple translation units, and it must be defined in every translation unit where it's used, and those definitions must be equivalent.
Mainly that solution allowed classes to be defined in header files.
No such language feature was needed to support data, variables defined in header files, so it just isn't there: you can't have inline variables. This is language deficiency #2.
However, you can obtain the effect of inline variables via a special exemption for static data members of class templates. The reason for the exemption is that class templates generally have to be fully defined in header files (unless the template is only used internally in a translation unit), and so for a class template to be able to have static data members, it's necessary with either an exemption from the general rules, or some special support. The committee chose the exemption-from-the-rules route.
template< class Dummy >
struct math_
{
static double const pi;
};
template< class Dummy >
double const math_<Dummy>::pi = 3.14;
typedef math_<void> math;
The above has been referred to as the templated const trick. As far as I know I was the one who once introduced it, in the [comp.lang.c++] Usenet group, so I can't give credit to someone else. I've also posted it a few times here on SO.
Anyway, this means that every C++ compiler and linker internally supports and must support the machinery needed for inline data, and yet the language doesn't have that feature.
However, on the third hand, C++11 has constexpr, where you can write the above as just
struct math
{
static double constexpr pi = 3.14;
};
Well, there is a difference, that you can't take the address of the C++11 math::pi, but that's a very minor limitation.
I think you're confusing two things: static data members and global variables markes as static.
The latter have internal linkage, which means that if you put their definition in a header file that multiple translation units #include, each translation unit will receive a private copy of those variables.
Global variables marked as const have internal linkage by default, so you won't need to specify static explicitly for those. Hence, the linker won't complain about multiple definitions of global const variable or of global non-const variables marked as static, while it will complain in the other cases (because those variables would have external linkage).
Concerning static data members, this is what Paragraph 9.4.2/5 of the C++11 Standard says:
static data members of a class in namespace scope have external linkage (3.5). A local class shall not have
static data members.
This means that if you put their definition in a header file #included by multiple translation units, you will end up with multiple definitions of the same symbol in the corresponding object files (exactly like non-const global variables), no matter what their const-qualification is. In that case, your program would violate the One Definition Rule.
Also, this Q&A on StackOverflow may give you a clearer understanding of the subject.

When should I write the keyword 'static' before a non-member function?

I've recently seen a bit on SO about the static keyword before a function and I'm wondering how to use it properly.
1) When should I write the keyword static before a non-member function?
2) Is it dangerous to define a static non-member function in the header? Why (not)?
(Side Question)
3) Is it possible to define a class in the header file in a certain way, so that it would only be available in the translation unit where you use it first?
(The reason that I'm asking this is because I'm learning STL and it might be a good solution for my predicates etc (possibly functors), since I don't like to define functions other than member-functions in the cpp file)
(Also, I think it is related in a way to the original question because according to my current reasoning, it would do the same thing as static before a function does)
EDIT
Another question that came up while seeing some answers:
4) Many people tell me I have to declare the static function in the header, and define it in the source file. But the static function is unique to the translation unit. How can the linker know which translation unit it is unique to, since header files do not directly relate to a source file (only when you include them)?
static, as I think you're using it, is a means of symbol hiding. Functions declared static are not given global visibility (a Unix-like nm will show these as 't' rather than 'T'). These functions cannot be called from other translation units.
For C++, static in this sense has been replaced, more or less, by the anonymous namespace, e.g.,
static int x = 0;
is pretty equivalent to
namespace {
int x = 0;
}
Note that the anonymous namespace is unique for every compilation unit.
Unlike static, the anonymous namespace also works for classes. You can say something like
namespace {
class Foo{};
}
and reuse that class name for unrelated classes in other translation units. I think this goes to your point 3.
The compiler actually gives each of the symbols you define this way a unique name (I think it includes the compilation time). These symbols are never available to another translation unit and will never collide with a symbol from another translation unit.
Note that all non-member functions declared to be inline are also by default static. That's the most common (and implicit) use of static. As to point 2, defining a static but not inline function in a header is a pretty corner case: it's not dangerous per se but it's so rarely useful it might be confusing. Such a function might or might not be emitted in every translation unit. A compiler might generate warnings if you never actually call the function in some TUs. And if that static function has within it a static variable, you get a separate variable per translation unit even with one definition in a single .h which might be confusing. There just aren't many (non-inline) use cases.
As to point 4, I suspect those people are conflating the static member function meaning of static with that of the linkage meaning of static. Which is as good a reason as any for using the anonymous namespace for the latter.
The keyword "static" is overloaded to mean several different things:
It can control visibility (both C and C++)
It can persist a variable between subroutine invocations (both C and C++)
... and ...
It can make a method or member apply to an entire class (rather than just a class instance: C++ only)
Short answer: it's best not to use ANY language facility unless
a) you're pretty sure you need it
b) you're pretty sure you know what you're doing (i.e. you know WHY you need it)
There's absolutely nothing wrong with declaring static variables or standalone functions in a .cpp file. Declaring a static variable or standalone function in a header is probably unwise. And, if you actually need "static" for a class function or class member, then a header is arguably the BEST place to define it.
Here's a good link:
http://www.cprogramming.com/tutorial/statickeyword.html
'Hope that helps
You should define non-member functions as static when they are only to be visible inside the code file they were declared in.
This same question was asked on cplusplus.com

Why field inside a local class cannot be static?

void foo (int x)
{
struct A { static const int d = 0; }; // error
}
Other than the reference from standard, is there any motivation behind this to disallow static field inside an inner class ?
error: field `foo(int)::A::d' in local class cannot be static
Edit: However, static member functions are allowed. I have one use case for such scenario. Suppose I want foo() to be called only for PODs then I can implement it like,
template<typename T>
void foo (T x)
{
struct A { static const T d = 0; }; // many compilers allow double, float etc.
}
foo() should pass for PODs only (if static is allowed) and not for other data types. This is just one use case which comes to my mind.
Because, static members of a class need to be defined in global a scope, e.g.
foo.h
class A {
static int dude;
};
foo.cpp
int A::dude = 314;
Since the scope inside void foo(int x) is local to that function, there is no scope to define its static member[s].
Magnus Skog has given the real answer: a static data member is just a declaration; the object must be defined elsewhere, at namespace scope, and the class definition isn't visible at namespace scope.
Note that this restriction only applies to static data members. Which means that there is a simple work-around:
class Local
{
static int& static_i()
{
static int value;
return value;
}
};
This provides you with exactly the same functionality, at the cost of
using the function syntax to access it.
Because nobody saw any need for it ?
[edit]: static variables need be defined only once, generally outside of the class (except for built-ins). Allowing them within a local class would require designing a way to define them also. [/edit]
Any feature added to a language has a cost:
it must be implemented by the compiler
it must be maintained in the compiler (and may introduce bugs, even in other features)
it lives in the compiler (and thus may cause some slow down even when unused)
Sometimes, not implementing a feature is the right decision.
Local functions, and classes, add difficulty already to the language, for little gain: they can be avoided with static functions and unnamed namespaces.
Frankly, if I had to make the decision, I'd remove them entirely: they just clutter the grammar.
A single example: The Most Vexing Parse.
I think this is the same naming problem that has prevented us from using local types in template instantiations.
The name foo()::A::d is not a good name for the linker to resolve, so how should it find the definition of the static member? What if there is another struct A in function baz()?
Interesting question, but I have difficulty understanding why you'd want a static member in a local class. Statics are typically used to maintain state across program flow, but in this case wouldn't it be better to use a static variable whose scope was foo()?
If I had to guess why the restriction exists, I'd say it was something to do with the difficulty for the compiler in knowing when to perform the static initialisation. The C++ standards docs might provide a more formal justification.
Just because.
One annoying thing about C++ is that there's a strong dependence on a "global context" concept where everything must be uniquely named. Even the nested namespaces machinery is just string trickery.
I suppose (just a wild guess) that one serious technical issue is working with linkers that were designed for C and that just got some tweak to get them working with C++ (and C++ code needs C interoperability).
It would be nice to be able to get any C++ code and "wrap it" to be able to use it without conflicts in a larger project, but this is not the case because of linkage problems. I don't think there is any reasonable philosophical reason for forbidding statics or non-inline methods (or even nested functions) at the function level but this is what we got (for now).
Even the declaration/definition duality with all its annoying verbosity and implications is just about implementation problems (and to give the ability to sell usable object code without providing the source, something that is now a lot less popular for good reasons).

Difference between static in C and static in C++??

What is the difference between the static keyword in C and C++?
The static keyword serves the same purposes in C and C++.
When used at file level (outside of a function), it sets the visibility of the item it's applied to. Static items are not visible outside of their compilation unit (e.g., to the linker). Their duration is the same as the duration of the program.
These file-level items (functions and data) should be static unless there's a specific need to access them from outside (and there's almost never a need to give direct access to data since that breaks the central tenet of encapsulation).
If (as your comment to the question indicates) this is the only use of static you're concerned with then, no, there is no difference between C and C++.
When used within a function, it sets the duration of the item. Again, the duration is the same as the program and the item continues to exist between invocations of that function.
It does not affect the visibility of that item since it's visible only within the function. An example is a random number generator that needs to keep its seed value between invocations but doesn't want that value visible to other functions.
C++ has one more use, static within a class. When used there, it becomes a single class variable that's common across all objects of that class. One classic example is to store the number of objects that have been instantiated for a given class.
As others have pointed out, the use of file-level static has been deprecated in favour of unnamed namespaces. However, I believe it'll be a cold day in a certain warm place before it's actually removed from the language - there's just too much code using it at the moment. And ISO C have only just gotten around to removing gets() despite the amount of time we've all known it was a dangerous function.
And even though it's deprecated, that doesn't change its semantics now.
The use of static at the file scope to restrict access to the current translation unit is deprecated in C++, but still acceptable in C.
Instead, use an unnamed namespace
namespace
{
int file_scope_x;
}
Variables declared this way are only available within the file, just as if they were declared static.
The main reason for the deprecation is to remove one of the several overloaded meanings of the static keyword.
Originally, it meant that the variable, such as in a function, would be given storage for the lifetime of the program in an area for such variables, and not stored on the stack as is usual for function local variables.
Then the keyword was overloaded to apply to file scope linkage. It's not desirable to make up new keywords as needed, because they might break existing code. So this one was used again with a different meaning without causing conflicts, because a variable declared as static can't be both inside a function and at the top level, and functions didn't have the modifier before. (The storage connotation is totally lost when referring to functions, as they are not stored anywhere.)
When classes came along in C++ (and in Java and C#) the keyword was used yet again, but the meaning is at least closer to the original intention. Variables declared this way are stored in a global area, as opposed to on the stack as for function variables, or on the heap as for object members. Because variables cannot be both at the top level and inside a class definition, extra meaning can be unambiguously attached to class variables. They can only be referenced via the class name or from within an object of that class.
It has the same meaning in both languages.
But C++ adds classes. In the context of a class (and thus a struct) it has the extra meaning of making the method/variable class members rather members of the object.
class Plop
{
static int x; // This is a member of the class not an instance.
public:
static int getX() // method is a member of the class.
{
return x;
}
};
int Plop::x = 5;
Note that the use of static to mean "file scope" (aka namespace scope) is only deoprecated by the C++ Standard for objects, not for functions. In other words,:
// foo.cpp
static int x = 0; // deprecated
static int f() { return 1; } // not deprecated
To quote Annex D of the Standard:
The use of the static keyword is
deprecated when declaring objects in
namespace scope.
You can not declare a static variable inside structure in C... But allowed in Cpp with the help of scope resolution operator.
Also in Cpp static function can access only static variables but in C static function can have static and non static variables...😊