В настоящее время я делаю относительно небольшой проект в Qt. Есть 2 object
s и 2 vector
s, которые должны быть доступны на протяжении всей жизни программы. Поэтому для этого я сделал 4 объявления в соответствующих заголовочных файлах, пометил их extern и определил их в MainWindow.cpp
, где я использую их в первый раз.
Однако ошибка при запуске std::out_of_range
возникает, когда создается один из объектов. После долгой сессии отладки я наконец-то нашел причину и источник ошибки:Объекты не созданы, когда они должны быть
mainwindow.cpp
#include "task.h" //Vectors; Works
#include "date.h" //Error
#include "db.h" //Works
std::vector<Task> task_vec; //extern from task.h
std::vector<Group> group_vec; //extern from task.h
Date date; //extern from date.h <- Error when instantinating this one
Database db; //extern from db.h
MainWindow::MainWindow(){//...}
//date and db objects are used in this file
date.cpp
#include "date.h" //it has "consants.h" included in it
//..Stuff
Date::Date()
{
//Use const int variable from "constants.h"
year = constants::START_YEAR; //Works, START_YEAR is initialized
year_count = constants::YEAR_COUNT //Works aswell
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(0).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)}
};
}
Я понятия не имею, почему. Если инициализированы START_YEAR
и YEAR_COUNT
, то остальная часть заголовка должна быть также, верно?
Вот где я объявить EXTERN объект:
date.h
//...Stuff
class Date
{
public:
Date();
Year& operator[](int);
private:
std::array<Year, constants::YEAR_COUNT> date_arr;
} extern date;
Думаю, я получил его, хотя я не мог обмотать голову вокруг этого на некоторое время. Спасибо за Ваш ответ! – 7Y3RPXK3ETDCNRDD
Подождите, стандарт имеет значение: Определяется реализацией независимо от того, выполняется ли динамическая инициализация (8.5, 9.4, 12.1, 12.6.1) объекта пространства имён перед первым утверждением main. Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования любой функции или объекта, определенных в той же самой единицы перевода, что и объект, который будет инициализирован. Таким образом, объекты из '' constants.h "' должны быть инициализированы перед вызовом конструктора 'Data'. – 7Y3RPXK3ETDCNRDD
«Первый оператор main()» - это не то же самое, что «единица перевода, которая включает main()». Кроме того, это говорит только о том, что «динамическая инициализация» может возникнуть или не произойти до «main()», но не указывает относительный порядок инициализации динамической инициализации объектов, объявленных в разных единицах перевода, она указывает только определенные вещи о «том же единица перевода как объект, подлежащий инициализации ». –