代码之家  ›  专栏  ›  技术社区  ›  Maleev

在C++中填充静态成员容器

  •  11
  • Maleev  · 技术社区  · 16 年前

    我有一个静态类成员,它是一个容器,比如

    (fo.h)

    class Foo
    {
       ...
    private:
       static list<string> s_List;
    }
    

    我需要用一些特定的值填充列表。事实上,它也应该 康斯特 但这可能会使问题进一步复杂化。 所有类成员函数都是静态的,所以在构造函数中初始化它是没有意义的。

    6 回复  |  直到 12 年前
        1
  •  15
  •   Idan K    16 年前

    一个常见的解决方案是这样做:

    // header
    class Foo
    {
    ...
    private:
       static list<string> s_List;
    }
    
    // cpp
    list<string> init()
    {
         list<string> tmp;
         ... fill tmp with strings
    
         return tmp;
     }
    
     list<string> Foo::s_List(init());
    

    另一种方法是尼尔·巴特沃斯建议的。

        2
  •  8
  •   anon    16 年前

    另一种选择是创建一个简单的初始化器类:

    list <string> Foo::s_List;
    
    struct Init {
       Init() {
          Foo::s_List.insert("apple");
          Foo::s_List.insert("bannana");
          Foo::s_List.insert("grapes");
       }
    };
    
    static Init doInit;
    

    注意,由于列表是私有的,这可能需要您将init作为foo的朋友。使这些类包含在它们初始化的类中通常也很方便。

    不过,我只是重新阅读了你的问题,然后又有了另一种想法——如果列表是常量,你大概不会改变它,在这种情况下,用字符串按排序顺序初始化的简单字符串数组可能是更好的解决方案。搜索(使用std::binary_search)肯定比搜索列表更快,当然也可以很容易地初始化。

        3
  •  4
  •   Jeffrey Grant    12 年前

    如果编译器支持C++ 0x,这实际上是微不足道的。

    #include <iostream>
    #include <list>
    
    class Foo
    {
    public:
       static std::list<std::string> s_List;
    };
    
    std::list<std::string> Foo::s_List = {"hello", "world", "asdf", "qwerty"};
    
    int main()
    {
        for(const std::string& str : Foo::s_List)
            std::cout << str << std::endl;
    
        return 0;
    }
    

    这对常量和非常量静态成员都有效。我用clang-4.2、gcc-4.7、gcc-4.6和gcc-4.5测试了这段代码。GCC-4.5不支持更新的 对于 语法,所以您必须使用传统的 对于 带迭代器的循环。另外,别忘了通过 - STD= C++0X 指向编译器的标志。我相当有信心Visual Studio也支持这一点,但我不确定,也不知道哪个版本。

        4
  •  1
  •   Brian Neal    16 年前

    这取决于您需要将哪些值放入该列表中。它们是静态的还是需要某种形式的计算?

    如果它们是静态的,可以这样做:

    namespace {
       const char* const initVals[] = { "A", "B", "C" };
    }
    
    list<string> Foo::s_list(initVals, initVals + 3);
    
        5
  •  0
  •   cobbal    16 年前

    一个可能的解决方案是使用一个访问器方法来检查它是否被初始化,如果没有初始化的话就这样做。

        6
  •  0
  •   Maleev    16 年前

    我(问题的作者)试图这样做的方式是徒劳的。


    我试着做类似smth的事情(在foo.cpp中):

    list<string> Foo::s_List = list<string>();
    Foo::s_List.insert("apple");
    Foo::s_List.insert("bannana");
    Foo::s_List.insert("grapes");
    

    但这会产生一个编译器错误。


    然后我想创建一个initialize()方法并从代码中直接调用它。

    void Foo::Initialize()
    {
        s_List.insert("rats");
        s_List.insert("cats");
    }
    
    Foo::Initialize(); 
    

    //错误:编译器认为它是方法的重新定义,而不是调用。


    唯一可行的想法是(还没有尝试)检查使用它的每个方法中的列表是否为空,如果是这样,请调用initialize()。但那太难看了!