C++ Where to Initialize Static Const

C++ where to initialize static const

Anywhere in one compilation unit (usually a .cpp file) would do:

foo.h

class foo {
static const string s; // Can never be initialized here.
static const char* cs; // Same with C strings.

static const int i = 3; // Integral types can be initialized here (*)...
static const int j; // ... OR in cpp.
};

foo.cpp

#include "foo.h"
const string foo::s = "foo string";
const char* foo::cs = "foo C string";
// No definition for i. (*)
const int foo::j = 4;

(*) According to the standards you must define i outside of the class definition (like j is) if it is used in code other than just integral constant expressions. See David's comment below for details.

How to initialize a static const member in C++?

YES you can but only for int types.
If you want your static member to be any other type, you'll have to define it somewhere in a cpp file.

class A{
private:
static const int a = 4; // valid
static const std::string t ; // can't be initialized here
...
...
};

// in a cpp file where the static variable will exist
const std::string A::t = "this way it works";

Also, note that this rule have been removed in C++11, now (with a compiler providing the feature) you can initialize what you want directly in the class member declaration.

Initialising a static const variable from a function in c

Unlike in C++ you cannot initialize global variables with the result of a function in C, but only with real constants known at compile time.

You need to write:

static const int size = 50;

If the constant must be computed by a function you can do this:

Dont declare static const int size = ... anymore, but write this:

int getSize()
{
static int initialized;
static int size;

if (!initialized)
{
size = SomeComplexFunctionOfYours();
initialized = 1;
}

return size;
}

int main(void)
{
...
int somevar = getSize();
...

That way SomeComplexFunctionOfYours() will be called only once upon the first invocation of getSize(). There is a small price to be paid: each time you invoke getSize(), a test needs to be performed.

Or you can initialize it explicitely like this, but then size cannot be const anymore:

static int size;

void InitializeConstants()
{
size = SomeComplexFunctionOfYours();
}

int main(void)
{
InitializeConstants();
...
int somevar = size;
...

Can I initialize static const class member?

The standard explicitly states that non-inline static data members of a class are declaration only, and must be followed up by definition at namespace scope: class.static.data#3

3:
The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member's class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the ​::​operator. The initializer expression in the definition of a static data member is in the scope of its class ([basic.scope.class]).

These rules are then refined further so that non-volatile non-inline const static data member of integral or enumeration type can be brace initialised (in effect defining the variable at the point of declaration): class.static.data#4

4: If a non-volatile non-inline const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression ([expr.const]). The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer. An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer.

In non-standardese speak, this says that you must define static member variables separately from the definition except for the case of integers or enums, which explains why your example fails.

static const member variable initialization

The syntax initializer in the class definition is only allowed with integral and enum types. For std::string, it must be defined outside the class definition and initialized there.

struct C {
static const int a = 42;
static const string b;
};

const string C::b = "hi"; // in one of the .cpp files

static members must be defined in one translation unit to fulfil the one definition rule. If C++ allows the definition below;

struct C {
static const string b = "hi";
};

b would be defined in each translation unit that includes the header file.

C++ only allows to define const static data members of integral or enumeration type in the class declaration as a short-cut. The reason why const static data members of other types cannot be defined is that non-trivial initialization would be required (constructor needs to be called).

Static const member initialization outside class

This is how to initialize static class members outside of the class:

C.cpp

#include <string>

class C {
public:
C();

private:
static const int a;
static const std::string b;
};

C::C() = default;

const int C::a = 4;
const std::string C::b = "ba";

There is no other option to initialize a static class member outside of the class, other than all the various C++ ways to do initialization as variations on this same theme.

static const double initialization in C++

static data members which are not constexpr can only be initialised directly at their declaration in the class definition if they are of integral or enumeration type. All other data types must be given a separate definition in a source file, and can only be initialised at that definition. So change your class definition to this:

class myclass
{
private:
static const double foo;
static const double bar;
};

and introduce these definitions into exactly one .cpp file:

const double myclass::foo = 3.1415;
const double myclass::bar = 12345.0 * foo;

If you have access to sufficiently modern C++, you have an alternative option of changing the in-class declarations to constexpr:

class myclass
{
private:
static constexpr double foo = 3.1415;
static constexpr double bar = 12345.0 * foo;
};

That way, they will not require a definition in a source file unless you use them as objects instead of as values (e.g. if you take their address). However, GCC 4.3.3 does not support that part of C++11.

Can I initialize a static const member at run-time in C++?

I am sorry to disagree with the comments and answers saying that it is not possible for a static const symbol to be initialized at program startup rather than at compile time.

Actually this IS possible, and I used it many times, BUT I initialize it from a configuration file. Something like:

// GetConfig is a function that fetches values from a configuration file
const int Param1 = GetConfig("Param1");
const int MyClass::Member1 = GetConfig("MyClass.Member1");

As you see, these static consts are not necessarily known at compile time. They can be set from the environment, such as a config file.

On the other hand, setting them from argv[], seems very difficult, if ever feasible, because when main() starts, static symbols are already initialized.



Related Topics



Leave a reply



Submit