C ++ - 将静态映射初始化为私有类成员

时间:2011-06-02 19:30:07

标签: c++ stl static map

假设我在一个傍晚非常无聊,在经常盯着电脑显示器几个小时之后,我决定实施一个聚合C ++类来管理绘制像素的颜色,因为我显然已经疯了。对于初学者,我们只是告诉(可能是单身)ColorManager对象我们想要使用的颜色,它将返回一个Color对象,无论可能是什么。一个简单的实现如下:

#include "Color.h"
#include <map>

enum COLOR { RED = 0, BLUE, GREEN, YELLOW, ORANGE, WHITE, BLACK,
    BRICKS_FROM_A_DISTANCE_ON_AN_UNUSUALLY_SUNNY_AFTERNOON,
    // etc
    COLOR_COUNT };

class ColorManager
{
public:
    ColorManager();
    ~ColorManager();
    Color getColor(COLOR color) const;
private:
    typedef std::map<COLOR, Color> ColorMap;
    static ColorMap colorMap;
};

所以,希望这个简单的代码:

ColorManger colorManager;
Color blue = colorManager.getColor(BLUE);

应该让我们真的很容易做任何你需要Color对象的废话。

问题是你需要在某处初始化静态私有ColorMap,以便每个COLOR枚举对应一个正确的Color对象,VC ++ 2010似乎不喜欢你尝试的任何东西。所以问题是,我如何以及在何处初始化这张地图?

显然,这是一个人为的例子,但除此之外,或许为一个作为单身的类定义静态变量并不值得。或者,也许,我可能只是在getColor()中声明变量static,因为这是使用它的唯一函数,并且只是在第一次调用函数时产生开销(尽管对于这个简单的例子,这并不是更好)而不只是在那里放一个巨大的开关声明)。无论如何,我都很感激反馈。

6 个答案:

答案 0 :(得分:14)

#include <map>
#include "Color.h"

enum COLOR
{
    RED = 0, BLUE, GREEN, YELLOW, ORANGE, WHITE, BLACK,
    BRICKS_FROM_A_DISTANCE_ON_AN_UNUSUALLY_SUNNY_AFTERNOON,
    // etc
    COLOR_COUNT
};

class ColorManager
{
    typedef std::map<COLOR, Color> ColorMap;

public:
    ColorManager();
    Color getColor(COLOR color) const;

private:
    static ColorMap createColorMap();
    static ColorMap colorMap;
};

// in some .cpp file:

ColorManager::ColorMap ColorManager::createColorMap()
{
    ColorMap ret;
    // populate ret
    return ret;
}

ColorManager::ColorMap ColorManager::colorMap = ColorManager::createColorMap();

或者使用C ++ 11:

#include <map>
#include "Color.h"

enum COLOR
{
    RED = 0, BLUE, GREEN, YELLOW, ORANGE, WHITE, BLACK,
    BRICKS_FROM_A_DISTANCE_ON_AN_UNUSUALLY_SUNNY_AFTERNOON,
    // etc
    COLOR_COUNT
};

class ColorManager
{
    using ColorMap = std::map<COLOR, Color>;

public:
    ColorManager();
    Color getColor(COLOR color) const;

private:
    static ColorMap colorMap;
};

// in some .cpp file:

ColorManager::ColorMap ColorManager::colorMap = []
{
    ColorMap ret;
    // populate ret
    return ret;
}();

答案 1 :(得分:6)

使用静态方法创建初始化地图:

ColorManager::colorMap(ColorManager::makeColorMap());

其中makeColorMap是以下静态方法:

ColorManager::ColorMap ColorManager::makeColorMap()
{
  ColorMap retval;
  retval[...] = ...;
  retval[...] = ...;
  ...

  return retval; 
}

答案 2 :(得分:6)

std :: map有一个构造函数,它将一对迭代器作为参数,因此您可以使用例如一对数组初始化映射:

#include "Color.h"

#include <map>

enum COLOR { RED = 0, BLUE, GREEN, YELLOW, ORANGE, WHITE, BLACK,
    BRICKS_FROM_A_DISTANCE_ON_AN_UNUSUALLY_SUNNY_AFTERNOON,
    // etc
    COLOR_COUNT };

class ColorManager
{
public:
    ColorManager();
    ~ColorManager();
    Color getColor(COLOR color) const;
private:
    typedef std::map<COLOR, Color> ColorMap;
    static ColorMap colorMap;
};

using std::make_pair;
using std::pair;

std::pair<COLOR, Color> colorPairs[] = {make_pair(RED, Color(...)),
                                        make_pair(BLUE, Color(...)),
                                        make_pair(GREEN, Color(...)),
                                        ...};

ColorManager::ColorMap ColorManager::colorMap(colorPairs, colorPairs + COLOR_COUNT);

在C ++ 0x中,您可以简单地执行此操作:

ColorManager::ColorMap ColorManager::colorMap({{RED, Color(...)},
                                               {BLUE, Color(...)},
                                               {GREEN, Color(...)},
                                               ...});

答案 3 :(得分:1)

一种选择是使用正确初始化地图内容的构造函数将ColorMaptypedef更改为自己的自定义类型。这样,当您静态初始化ColorMap时,构造函数将使用正确的数据填充它,并且尝试使用ColorManager的任何操作都将看到正确配置的ColorMap

答案 4 :(得分:1)

你可以这样做而不需要上课:

Color getColor(COLOR color)
{
      static std::map<COLOR, Color> colorMap;
      if(colorMap.empty()) // Only runs once.
      {
          colorMap[BLUE] = Color();
          // ... etc ...
      }

      return colorMap[color];
}

答案 5 :(得分:-2)

您在.cpp中将其初始化为

ColorManager::ColorMap ColorManager::colorMap;

并在ColorManager构造函数中创建Color的所有实例并填充。