2010-12-27 2 views
1

при условии, у меня есть объект, похожий на этот:скобка огороженного списка инициализатора

struct MenuDef 
{ 
    int titleResourceId; 

    struct MenuItemDef { 
     char*    name; 
     int     value; 
     SomeFunctionPtr  someFactory; 
    } menuItems[10]; 
}; 

Это инициализируется следующим образом:

const MenuDef m = { 
    1, 
    { 
     { 
      "zero", 
      0, 
      (SomeFunctionPtr) & MenuButton::factory, 
     }, 
     { 
      "one", 
      1, 
      (SomeFunctionPtr) & MenuButton::factory, 
     }, 
     { 
      "two", 
      2, 
      (SomeFunctionPtr) & MenuButton::factory, 
     }, 
    } 
}; 

Безопасно предположить, чтоm.menuItems[3].someFactory == 0?

, например, в цикле, как это:

for (int i = 0; m.menuItems[i].someFactory != 0; ++i) 

или я должен вставить последний элемент, чтобы отметить конец массива вручную на всякий случай?

... 
     { 
      "two", 
      2, 
      (SomeFunctionPtr) & MenuButton::factory, 
     }, 
     { 
      "", 
      0, 
      (SomeFunctionPtr) 0, 
     }, 
... 
+1

Это не отвечает на ваш вопрос (я думаю, что @icecrime правильно понял), но тот факт, что вы должны указывать адреса функций при инициализации, должен быть большим красным флагом. Даже если это сейчас работает, в будущем ваш компилятор может измениться, и он не сможет работать из-за кастинга между несовместимыми типами указателей функций. –

+0

@Mark B не уверен, что вы имеете в виду ... можете ли вы привести пример? –

ответ

4

Я считаю, что это безопасно в соответствии с 8.5.1/7:

Если меньше Инициализаторы в списке, чем входящие в совокупности, то каждый член не явно инициализировано должно быть инициализировано значение (8.5).

В качестве напоминания:

Для того, чтобы значение инициализации объекта типа Т означает:

  • , если Т представляет собой тип класса (пункт 9) с пользователем объявлено конструктором (12.1), , тогда конструктор по умолчанию для T называется (и инициализация плохо сформирована, если T не имеет доступного конструктора по умолчанию );
  • если Т не является объединением типа класса без пользовательской объявленной конструкторы, то каждый нестатический член данных и базового класс компонента Т значения инициализировано;
  • если T - тип массива, то каждый элемент инициализируется значением;
  • в противном случае, объект нулевой инициализируется
+0

Вам не нужен конструктор по умолчанию для инициализации значений до 0? Я также рекомендую не полагаться на это, сохраняя размер вместо этого, чтобы сделать его более читаемым или даже изменить на «вектор». – marcog

+0

@marcog: обновил мой ответ с помощью определения инициализации значения. Согласно этой цитате, я считаю, что вам не нужен конструктор, объявленный пользователем. – icecrime

+0

Не является ли 'struct' классом типа? – marcog

2

Ответ на ваш вопрос зависит от версии языка (C++ 98 или C++ 03), и в C++ 98, о некоторых деталях, которые вы не смогли предоставить. А именно, что такое SomeFuncPtr? Является ли это обычным указателем функции или указателем на функцию-член?

Если это указатель на функцию-член, то в версии языка C++ 98 внутренний класс не является POD. Поскольку это не-POD-класс, остальные члены массива будут инициализироваться по умолчанию, вызвав их конструкторы по умолчанию. Предоставляемый компилятором конструктор по умолчанию для внутреннего класса ничего не делает, поэтому остальные члены массива будут содержать мусор.

В версии языка C++ 03 оставшиеся элементы массива инициализируются инициализацией по значению, что в действительности инициализирует остальную часть массива независимо от того, что такое SomeFuncPtr.

Итак, если вы используете компилятор, совместимый с C++ 03, вы в порядке. Если вам интересно переносить исходные тексты на компиляторы C++ 98, вы можете включить этот явный завершающий инициализатор (в зависимости от того, что такое SomeFuncPtr).

+0

Хорошо. Я получаю людей, которые не хотят ответов на C++ 0x. Но, давайте, вам не придется иметь дело с C++ 98. – Puppy

+0

+1. На самом деле это статическая функция-член (которая почти такая же, как обычный указатель функции). Но спасибо за разъяснение, так как я не уверен, что компилятор, совместимый с C++ 03, доступен для всех платформ, которые мне нужно развернуть. :) –