user393964
user393964

Reputation:

const array declaration in C++ header file

I have a class called AppSettings where I have an Array with a range of note frequencies. I'm getting several errors with the code below and I'm not sure what the problem is.

The error messages are:

And the code:

class AppSettings{

public:
    static const float noteFrequency[36] = {
    //  C       C#      D       D#      E       F       F#      G       G#      A       A#      B
        130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
        261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
        523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
    };

};

As the name suggests this is just a header file with some settings and values I need throughout the app.

Upvotes: 18

Views: 24848

Answers (3)

KRyan
KRyan

Reputation: 7598

You can't define the value of static class members within the class. You need to have a line like this in the class:

class AppSettings
{
public:
    static const float noteFrequency[];

And then in an implementation file for the class (AppSettings.cpp perhaps):

const float AppSettings::noteFrequency[] = { /* ... */ };

Also, you don't need to specify the number within the [] here, because C++ is smart enough to count the number of elements in your initialization value.

Upvotes: 30

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145214

C++03 doesn't support in-class definitions of complex data like arrays of constants.

To place such a definition at namespace scope in a header file, and avoid breaking the One Definition Rule, you can leverage a special exemption for template classes, as follows:

#include <iostream>
using namespace std;

//----------------------------------------- BEGIN header file region
template< class Dummy >
struct Frequencies_
{
    static const double noteFrequency[36];
};

template< class Dummy >
double const Frequencies_<Dummy>::noteFrequency[36] =
{
    //  C       C#      D       D#      E       F       F#      G       G#      A       A#      B
    130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
    261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
    523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
};

class AppSettings
    : public Frequencies_<void>
{
public:
};
//----------------------------------------- END header file region

int main()
{
    double const a = AppSettings::noteFrequency[21];

    wcout << a << endl;
}

There are also some other techniques that can be used:

  • An inline function producing a reference to the array (or used as indexer).

  • Placing the definition in a separately compiled file.

  • Simply computing the numbers as needed.

Without more information I wouldn’t want to make the choice for you, but it shouldn’t be a difficult choice.

Upvotes: 7

rubenvb
rubenvb

Reputation: 76519

This works just fine in C++11

class AppSettings{

public:
    static constexpr float noteFrequency[36] = {
//  C       C#      D       D#      E       F       F#      G       G#      A       A#      B
    130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 223.08, 246.94,
    261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
    523.25, 554.37, 587.33, 622.25, 659.25, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77
    };

};

Upvotes: 13

Related Questions