У меня есть следующий код в моем проекте:Объекты с глобальным объектом не инициализируются рекурсивно?
mainwindow.cpp
#include "date.h"
Date date; //extern from date.h <- Error when instantinating this one
MainWindow::MainWindow(){//...}
date.cpp
#include "date.h"
#include "consants.h"
//..Stuff
Date::Date()
{
//Use const int variable from "constants.h"
year = constants::START_YEAR; //Works, START_YEAR is initialized
Month month(m, y);
}
Month::Month(int month, int year)
{
//Use const std::map<QString, std::pair<int,int>> from "constants.h"
day_count = constants::MONTH_DAY_MAP_LY.at("January").second //ERROR, MONTH_DAY_MAP_LY is not initialized
}
constants.h
namespace constants {
const int START_YEAR = 2016;
const int YEAR_COUNT = 83;
const QList<QString> MONTH { "January", "February", "March",
"April", "May", "June", "July", "August", "September", "October", "November", "December"};
const std::map<QString, std::pair<int, int>> MONTH_DAY_MAP{
{MONTH[0], std::make_pair(0, 31)}, {MONTH[1], std::make_pair(1, 28)}, {MONTH[2], std::make_pair(2, 31)},
{MONTH[3], std::make_pair(3, 30)}, {MONTH[4], std::make_pair(4, 31)}, {MONTH[5], std::make_pair(5, 30)},
{MONTH[6], std::make_pair(6, 31)}, {MONTH[7], std::make_pair(7, 31)}, {MONTH[8], std::make_pair(8, 30)},
{MONTH[9], std::make_pair(9, 31)}, {MONTH[10], std::make_pair(10, 30)}, {MONTH[11], std::make_pair(11, 31)}
};
const std::map<QString, std::pair<int, int>> MONTH_DAY_MAP_LY {
{MONTH[0], std::make_pair(0, 31)}, {MONTH[1], std::make_pair(1, 29)}, {MONTH[2], std::make_pair(2, 31)},
{MONTH[3], std::make_pair(3, 30)}, {MONTH[4], std::make_pair(4, 31)}, {MONTH[5], std::make_pair(5, 30)},
{MONTH[6], std::make_pair(6, 31)}, {MONTH[7], std::make_pair(7, 31)}, {MONTH[8], std::make_pair(8, 30)},
{MONTH[9], std::make_pair(9, 31)}, {MONTH[10], std::make_pair(10, 30)}, {MONTH[11], std::make_pair(11, 31)}
};
}
Как вы видите, я получаю ошибку std::out_of_range
при попытке получить доступ к MONTH_DAY_MAP_LY
. После сеанса отладки я понял, что это происходит потому, что конструктор Date
вызывается перед любой другой функцией (даже основной). Но я также нашел эту страницу в стандарте:
Она определяется реализацией или нет динамической инициализации (8.5, 9.4, 12.1, 12.6.1) объекта из области видимости пространства имен производится перед первым оператором основного. Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования любой функции или объекта, определенных в той же самой единицы перевода, что и объект, который будет инициализирован.
Поскольку это правило относится и к Date date
и объекты из constants.h
я не знаю, почему линкер инициализирует Date date
и только int
s из constants.h
.
Подробнее о [статической ошибке инициализации фиаско *] (http://stackoverflow.com/q/3035422/440558). Особенно прочтите первый абзац [самый высокий голосовой ответ] (http://stackoverflow.com/a/3036852/440558). –