简体   繁体   中英

C++: static initialize an array member, member at a time

I now I can do this in global scope and everything works fine:

const char* Foo::bars[3] = {"a", "b", "c"};

But I want to do this because this is much more clearer and self documenting (especially if you use Enums as the index):

const char* Foo::bars[3];
bars[0] = "a";
bars[1] = "b";
bars[2] = "c";

Is it anyway possible?

I know I can do this inside a function (for example, the class's constructor) but what if the constructor is not called in the start of the program and I want to use the static array? That leads to problems.

How about this?

const char* Foo::bars[3] = {
/* Index    Value */
/* 0 */     "a",
/* 1 */     "b",
/* 2 */     "c"
};

I often use this "technique" to make the initialization of arrays of structs look like a self-documenting spreadsheet.

In C++ there is no equivalent of the static Java block.

If you really want to initialize the array automatically, you can create a simple class to do the job:

// in .cpp
class FooInitializer {
public:
    FooInitializer() {
        Foo:bars[0] = "a";
        Foo:bars[1] = "b";
        Foo:bars[2] = "c";
    }
};

static FooInitializer fooInitializer;

You can use an accessor-function:

const char* GetArray()
{
    static char* result[3];
    static isInitialized = false;
    if (!isInitialized)
    {
        result[0] = "a";
        result[1] = "b";
        result[3] = "c";
        initialized=true;
    }
    return result;
}

Here's another solution that uses the Singleton pattern. Note that the array is initialized once in the singleton's constructor. Also note that this is not thread-safe. Also beware of the evilness of singletons (search this site for "singleton" to find some interesting debate on this matter).

#include <iostream>

class StringTable
{
public:
    enum StringId
    {
        hello,
        bye,
        goodDay,
        stringCount
    };

    static const char* lookup(StringId id) {return instance().table_[id];}

private:
    StringTable()
    {
        table_[hello] = "Hello World!\n";
        table_[bye] = "Goobye, cruel world!\n";
        table_[goodDay] = "I said good day!\n";
    }

    static StringTable& instance()
    {
        static StringTable theInstance;
        return theInstance;
    }

    const char* table_[stringCount];
};


int main()
{
    std::cout << StringTable::lookup(StringTable::hello)
              << StringTable::lookup(StringTable::bye)
              << StringTable::lookup(StringTable::goodDay);
}

You probably want an extra const in bars

const char* const Foo::bars[3] = 
{
   "a",
   "b",
   "c"
};

The way you declared it, you can actually do what you wanted in setting the members one at a time, although you'd use an "init" function to do it.

If you do want it const, which is probably preferable, it will subsequently become illegal to assign them a line at a time, even in some kind of "init" method and you should simply use a code layout to make it clearer what you are doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM