50

I have just found out that the following is not valid.

//Header File
class test
{
    const static char array[] = { '1', '2', '3' };
};

Where is the best place to initialize this?

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
user174084
  • 1,087
  • 3
  • 14
  • 23

6 Answers6

55

The best place would be in a source file

// Header file
class test
{
    const static char array[];
};

// Source file
const char test::array[] = {'1','2','3'};

You can initialize integer types in the class declaration like you tried to do; all other types have to be initialized outside the class declaration, and only once.

midor
  • 5,487
  • 2
  • 23
  • 52
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Shouldn't that say "... in the class *declaration*..."? I thought `.h` were declarations and `.c` were definitions, hence why taking a reference to an integer type that is declared only in the header results in a compiler error: `undefined reference to test::SOME_INTEGER`? (I realize this sounds super nit-picky and pedantic, and I'm not trying to be difficult; I just want to make sure I'm using the right terminology, so definitely correct me if I'm wrong). – dwanderson Feb 15 '16 at 15:55
37

You can always do the following:

class test {
  static const char array(int index) {
    static const char a[] = {'1','2','3'};
    return a[index];
  } 
};

A couple nice things about this paradigm:

JKD
  • 623
  • 5
  • 8
21
//Header File 
class test 
{ 
    const static char array[];
}; 

// .cpp
const char test::array[] = { '1', '2', '3' }; 
peterchen
  • 40,917
  • 20
  • 104
  • 186
12

Now, in C++17, you can use inline variable

How do inline variables work?

A simple static data member(N4424):

struct WithStaticDataMember {
  // This is a definition, no out­of­line definition is required.
  static inline constexpr const char *kFoo = "foo bar";
};

In your example:

//Header File
class test
{
    inline constexpr static char array[] = { '1', '2', '3' };
};

should just work

Community
  • 1
  • 1
lz96
  • 2,816
  • 2
  • 28
  • 46
2

With constexpr you must define the value on the header even in C++11

If you use constexpr instead of const, then this answer suggests that you not only can, but must, define on header even in C++11:

#include <cassert>

struct MyClass {
    static constexpr int is[] = {1, 2, 3};
    static constexpr int i = 1;
};

// TODO is this ever mandatory? Create example that fails on -std=c++11.
// Pretty sure never mandatory in C++17 https://stackoverflow.com/a/40959093/895245
// constexpr int MyClass::is[];

int main (void) {
    assert(MyClass::is[0] == 1);
    assert(&MyClass::is[0] == &MyClass::is[1] - 1);
    assert(MyClass::i == 1);
    assert(&MyClass::i == &MyClass::i);
}

Compile and run with:

g++-10 -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out 

If instead you try:

struct MyClass {
    static constexpr int is[];
};

constexpr int MyClass::is[] = {1, 2, 3};

compilation fails with:

main.cpp:4:26: error: ‘constexpr’ static data member ‘is’ must have an initializer

Tested on Ubuntu 20.04.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

This is kind of an abuse of the system, but if you REALLY want to define it in the header file (and you don't have C++17), you can do this. It won't be a static member, but it will be a constant that only takes up storage per compilation unit (rather than per class instance):

(Put all of this code in the header file.)

namespace {
    const char test_init_array[] = {'1', '2', '3'};
}

class test {
public:
    const char * const array;

    test() : array(test_init_array) {}
};
Jim Hunziker
  • 14,111
  • 8
  • 58
  • 64