views:

9425

answers:

4

This is related to some other questions, such as: this, and some of my other questions.

In this question, and others, we see we can declare and initialise string arrays in one nice step, for example:

const char* const list[] = {"zip", "zam", "bam"}; //from other question

This can be done in the implementation of a function with no bother, or in the body of a .cpp file, outside any scope.

What I want to do is to have an array like this as as member of a class I am using, something like this:

class DataProvider : public SomethingElse
{
    const char* const mStringData[] = {"Name1", "Name2", "Name3", ... "NameX"};

public:
    DataProvider();
    ~DataProvider();

    char* GetData()
    {
        int index = GetCurrentIndex(); //work out the index based on some other data
        return mStringData[index]; //error checking and what have you omitted
    }

};

But, the compiler complains and I can't seem to work out why. Is it possible to declare and initialise an array like this in one step in a class definition? Are there alternatives that are better?

I'm sure this is a very amateur mistake, but as always, your help and advice is much appreciated.

Cheers,

xan

+2  A: 

This is not possible in C++. You cannot directly initialize the array. Instead you have to give it the size it will have (4 in your case), and you have to initialize the array in the constructor of DataProvider:

class DataProvider {
    enum { SIZEOF_VALUES = 4 };
    const char * values[SIZEOF_VALUES];

    public:
    DataProvider() {
        const char * const v[SIZEOF_VALUES] = { 
            "one", "two", "three", "four" 
        };
        std::copy(v, v + SIZEOF_VALUES, values);
    }
};

Note that you have to give up on the const-ness of the pointers in the array, since you cannot directly initialize the array. But you need to later set the pointers to the right values, and thus the pointers need to be modifiable.

If your values in the array are const nevertheless, the only way is to use a static array:

/* in the header file */
class DataProvider {
    enum { SIZEOF_VALUES = 4 };
    static const char * const values[SIZEOF_VALUES];
};

/* in cpp file: */

const char * const DataProvider::values[SIZEOF_VALUES] = 
    { "one", "two", "three", "four" };

Having the static array means all objects will share that array. Thus you will have saved memory too.

Johannes Schaub - litb
+3  A: 

The reason you can't declare your array like that (const char* []) is that:

  • you can't have initializers in the class declaration, and so
  • the syntax const char* [] does not state how much space the compiler needs to allocate for each instance (your array is declared as instance variable).

Besides, you probably want to make that array static, since it is in essence a constant value.

Carl Seleborg
+15  A: 

Use the keyword static and external initialization to make the array a static member of the class:

In the header file:

class DataProvider : public SomethingElse
{
    static const char* const mStringData[];

public:
    DataProvider();
    ~DataProvider();

    const char* const GetData()
    {
        int index = GetCurrentIndex(); //work out the index based on some other data
        return mStringData[index]; //error checking and what have you omitted
    }

};

In the .cpp file:

const char* const DataProvider::mStringData[] = {"Name1", "Name2", "Name3", ... "NameX"};
Stefan Rådström
You need to give the array a size in the header declaration.
mbyrne215
Are you sure? It work fine for me (Visual C++ 2005) and I have been using it previously a few times. Unless it is undefined behaviour in the standard (which I will not look up now), I believe it will work.
Stefan Rådström
You are fine while using the initialiser. The compiler will calculate the size based on the number of items in the initialiser.
Martin York
Yeah i think it's valid to omit the size, the array is incomplete then. But in the header, you won't know the size of the array then indeed. so no sizeof on it possible too -.-
Johannes Schaub - litb
You're right; momentary brain lapse.
mbyrne215
Well, since the OP is using a (member) function, GetCurrentIndex(), it can use the sizeof operator if it is defined in the same .cpp file.
Stefan Rådström
The header can probably use 'static const char** const mStringData;', since arrays are poninters anyway.
Tom Leys
yes. you are rite :) the no-size-of was meant to refer to the functions in the header-file :)
Johannes Schaub - litb
This is what I was looking for, and yes, I should have made the array static from the beginning!Thanks for all suggestsions!
xan
A: 

WOW this has been really helpful! I am dealing with a similar issue... only I have a 2D array:

Header File:

 class FireWeatherWRF{
  private:
    dblptr *data_array = new dblptr[SN];
    for (int i=0;i<SN;i++) {data_array[i]= new dblptr[WE];}
  }

Constructor from Implementation File:

  FireWeatherWRF::FireWeatherWRF(){
    for (int lat=0;lat<SN;lat++){
      for (int lon=0;lon<WE;lon++){
        data_array[lat][lon]=0;
      }
    }
    loaded=false;
  }

How does one go about declaring a pointer to an array or arrays in a header file?

stavros