0

这是旧主题的另一个变体:不同翻译单元中静态对象的初始化顺序没有定义。

下面是我的特定场景的精简示例。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

文件系统

#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 的构造函数接受一个参数,该参数是应用于 G 的实例的结果 operator+。由于 F 和 G 的实例都是全局变量,因此不能保证 G 的实例在 F 的构造函数需要它们时已经被初始化。

这里的特殊性是到处都有很多 G 和 F,我想尽可能地保持语法接近上面发布的代码,同时仍然在 F 需要时强制构造 G。

4

3 回答 3

1

来自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;
}

或者如果你实在无法忍受添加额外()的 s,使用 some #defines 来隐藏它们:

// Gs.hpp
const G & get_g1();
#define g1 (get_g1())
// Definition of get_g1() like g1() from prev. example
于 2010-09-29T22:25:36.337 回答
0

将外部声明保留在标题中。以适当的顺序将所有fNgN定义放入单个 cpp 文件中。

于 2010-09-29T22:18:09.627 回答
0

也许类似于用于初始化cin和朋友的文件缓冲区的技巧对您有用?(<iostream>仔细阅读。)

于 2010-09-29T22:21:53.783 回答