учебная задача на инициализацию статических переменных
Всем привет. Есть учебная задача . Как эту задачу сделать мне непонятно. Я постарался сделать дословно что просят, но свести к результату не выходит (то есть добиться что просят в последнем предложении текста задачи)
вот моя реализация . я конструкторы сделал более информативными (то есть первый конструктор стал вовсе не по умолчанию, у него появился параметр и у второго конструктора добавился ещё и второй параметр - этого в задаче не просят (это для себя)), выводя какая переменная запросила конструктор . суть задачи в том как понимаю, что при компоновки последовательность файлов может быть разной. Но в любом случае test() в main выдаст true потому что рекурсивно функция выполнится вплоть до A1 в которой как бы конструктор по умолчанию (на самом деле я его сделал с параметром для информативности) . То есть я подозреваю , что я неверно понял и соответственно реализовал задачу.
s4.cpp
#include "H1.h"
extern Mirror A1;
Mirror A2("A2", &A1);
s1.cpp
#include "H1.h"
extern Mirror A2;
Mirror A3("A3", &A2);
s2.cpp
#include "H1.h"
extern Mirror A3;
Mirror A4("A4", &A3);
s3.cpp
#include "H1.h"
Mirror A1("A1");
s5.cpp
#include "H1.h"
extern Mirror A4;
Mirror A5("A5",&A4);
void main() {
std::cout << A5.test() << std::endl;
}
и заголовочник :
#include <iostream>
class Mirror {
Mirror* M;
std::string MNAME;
bool b;
public:
Mirror(std::string var) : M(0), b(true), MNAME(var){
std::cout << var <<"(default)"<< std::endl;
}
Mirror(std::string var, Mirror* M1) : M(M1), b(false), MNAME(var) {
std::cout << var << std::endl;
}
bool test() {
if (M != 0) return M->test(); else return b;
}
};
Ответы (1 шт):
Попробую перевести задачу на человеческий язык. Это задача на то как влияет порядок статической инициализации на поведение программы.
В формулировке из картинки задача неразрешима. Каков бы ни был порядок инициализации пяти объектов, в момент когда мы попадаем в main они все созданы и все запомнили правильные указатели из цепочки. Когда вы вызовете A5.test() вся цепочка будет пройдена и в ответе будет true из A1.
Чтобы демострация сработала надо сделать две вещи:
1. Надо убрать std::string из объекта. Задача предполагает, что объект является почти POD. Добавив name вы нарушили это условие. Если объект почти POD, то компоновщик заполнив объекты нулями сделает их полуживыми. Заполнение нулями поля std::string просто сломает его.
Объекты будут "полуживыми" так как стандарт запрещает их использовать до вызова конструктора. Но идея задачи как раз в том чтобы сделать это.
2. Надо переделать конструктор:
Mirror(Mirror* M1, const std::string& name) : M(M1), b(M1->test()) {
std::cout << name << std::endl;
}
Я вызвал M1->test() в конструкторе. Если объект M1 ещё не сконструирован, то он заполнен нулями. Метод test вернёт false, который мы скопируем в конструируемый объект.
Если в нашей цепочке будет хотя бы одна пара инициализаций в "неправильном" порядке, то в main вернётся false. Если все инициализации будут упорядочены A1, A2, A3, A4, A5, то вернётся true.
Ключевой ингредиент задачи - исполнение кода (или чтение данных из) объекта который ещё не конструировался.

