Я использую стороннюю библиотеку C ++, для которой требуется определение глобального массива структур. Мне не нравится этот дизайн, но я застрял с ним.
LibStruct g_Structs[] =
{
{ /* structure initialization data */ },
{ /* structure initialization data */ },
// etc
};
int g_NumStructs = sizeof(g_Structs) / sizeof(g_Structs[0]);
Я бы хотел немного разбить это, чтобы классы могли предоставить определение структуры, которое применимо к этому классу. Это может привести к фиаско статической инициализации, если инициализация не будет выполнена безопасно с использованием геттеров или после начала main ().
Если я объявляю MyStructs для каждого класса в заголовочном файле для этого класса как статические члены данных с атрибутом __declspec (selectany) (специфичным для Visual C ++), тогда кажется работающим. Влияет ли атрибут selectany на порядок построения этих данных? Означает ли появление определения selectany статического члена данных перед глобальным массивом фактически то, что он построен в таком порядке? Или это поведение зависит только от того, какое из определений множественного выбора выбрасывается компоновщиком? Есть ли гарантии у selectany?
// In the header for Class1
static const LibStruct __declspec(selectany) Class1::m_MyStruct = { /* structure initialization data */ };
// In the header for Class2
static const LibStruct __declspec(selectany) Class2::m_MyStruct = { /* structure initialization data */ };
// Danger - potential for static initialization fiasco?
LibStruct g_Structs[] =
{
Class1::m_MyStruct,
Class2::m_MyStruct,
// etc
};
int g_NumStructs = sizeof(g_Structs) / sizeof(g_Structs[0]);
РАЗЪЯСНЕНИЯ:
В этом случае MyStruct - это структура в стиле C, которая не имеет конструкторов или виртуальных функций и содержит только указатели, которые все инициализированы, чтобы указывать на другие глобальные данные или функции, не являющиеся членами. Поэтому инициализация глобального константного MyStruct с использованием синтаксиса = {} не должна запускать код конструктора.