C ++ - Инициализация статической карты как члена частного класса - PullRequest
17 голосов
/ 02 июня 2011

Допустим, мне было довольно скучно поздно вечером, и после кататонического взгляда на монитор компьютера в течение нескольких часов я решил реализовать агрегатный класс 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, похоже, ничего вам не пытался. Итак, вопрос в том, как и где мне инициализировать эту карту?

Очевидно, что это надуманный пример, но помимо этого, возможно, определение статических переменных для класса, который функционирует как одиночный, не стоит проблем. Или, может быть, я мог бы просто объявить переменную static внутри getColor (), поскольку это единственная функция, которая ее использует, и просто понести издержки при первом вызове функции (хотя для этого простого примера это не намного лучше чем просто поместить гигантское заявление о переключении там). В любом случае, я ценю обратную связь.

Ответы [ 6 ]

14 голосов
/ 02 июня 2011
#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;
}();
6 голосов
/ 03 июня 2011

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(...)},
                                               ...});
6 голосов
/ 02 июня 2011

использовать статический метод, который создает инициализированную карту:

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

, где makeColorMap - следующий статический метод:

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

  return retval; 
}
1 голос
/ 02 июня 2011

Вы можете сделать это так без использования класса:

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

      return colorMap[color];
}
1 голос
/ 02 июня 2011

Один из вариантов - изменить ColorMap с typedef на собственный настраиваемый тип с помощью конструктора, который правильно инициализирует содержимое карты.Таким образом, когда вы статически инициализируете ColorMap, конструктор заполнит его правильными данными, и любые операции, которые пытаются использовать ColorManager, увидят правильно сконфигурированный ColorMap.

0 голосов
/ 02 июня 2011

Вы инициализируете его в .cpp как

ColorManager::ColorMap ColorManager::colorMap;

, а в конструкторе ColorManager создаете все экземпляры Color и заполняете его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...