Проблема статического порядка инициализации в C ++ - PullRequest
0 голосов
/ 30 сентября 2010

Это еще один вариант старой темы: порядок инициализации статические объекты в разных единицах перевода не определены.

Ниже приведен упрощенный пример моего конкретного сценария. классы G и F не являются типами POD. F зависит от G в том смысле, что построить экземпляр F вам нужно некоторое количество экземпляров G. (Например, F может быть каким-то сообщением, которое излучает приложение, и экземпляры G будут компонентами таких сообщений.)

G.hpp

#ifndef G_HPP
#define G_HPP

struct G
{
    G() {} // ...
};

inline G operator+(G, G) { return G(); }

#endif

Gs.hpp

#ifndef GS_HPP
#define GS_HPP

#include "G.hpp"

extern const G g1;
extern const G g2;
extern const G g3;
extern const G g4;
extern const G g5;
extern const G g6;
extern const G g7;
extern const G g8;
extern const G g9;

#endif

Gs.cpp

#include "Gs.hpp"

const G g1;
const G g2;
const G g3;
const G g4;
const G g5;
const G g6;
const G g7;
const G g8;
const G g9;

F.hpp

#ifndef F_HPP
#define F_HPP

#include "G.hpp"

struct F
{
    F(G) {} // ...
};

#endif

Fs.hpp

#ifndef FS_HPP
#define FS_HPP

#include "F.hpp"

extern const F f1;
extern const F f2;
extern const F f3;

#endif

Fs.cpp

#include "Fs.hpp"
#include "Gs.hpp"

const F f1(g1 + g2 + g3);
const F f2(g4 + g5 + g6);
const F f3(g7 + g8 + g9);

Конструктор F принимает аргумент, который является результатом применения operator+ к экземплярам G. Поскольку экземпляры как F, так и G глобальные переменные, нет гарантии, что экземпляры G имеют был инициализирован, когда конструктор F нуждается в них.

Особенность здесь в том, что по всему место, и я хотел бы сохранить синтаксис как можно ближе к приведенному выше коду, при этом все еще применяя конструкцию G всякий раз, когда F нуждается в этом.

Ответы [ 3 ]

1 голос
/ 30 сентября 2010

С http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15.

Измените ваши глобальные объекты на функции, которые создают объект при первом использовании.

// Gs.hpp
const G & g1();

// Gs.cpp
const G & g1() {
  static const G* g1_ptr = new G();
  return *g1_ptr;
}

// Fs.cpp
const F & f1() {
  static const F* f1_ptr = new F(g1() + g2() + g3());
  return *f1_ptr;
}

Или, если вы действительно не можете терпеть добавлениедополнительные () с, используйте некоторые #define с, чтобы скрыть их:

// Gs.hpp
const G & get_g1();
#define g1 (get_g1())
// Definition of get_g1() like g1() from prev. example
0 голосов
/ 30 сентября 2010

Может быть, уловка, подобная той, которая использовалась для инициализации cin и файловые буферы друзей, подойдет вам? (Внимательно прочитайте <iostream>.)

0 голосов
/ 30 сентября 2010

Храните внешние объявления в заголовках.Поместите все определения fN и gN в один файл cpp в соответствующем порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...