使用静态const成员初始化c ++中的另一个静态const

时间:2017-05-28 15:32:57

标签: c++ static const

我遇到以下问题:

我有一个Color类,为了这个问题的目的,减少到:

// Color.h
struct Color {
    int r,g,b;
    Color() : r(0), g(0), b(0) {}
    Color(int r_, int g_, int b_) : r(r_), g(g_), b(b_) {}
    static const Color Red;
    static const Color Magenta;
};

// Color.cpp
#include "Color.h"
const Color Color::Red (255,0,0);
const Color Color::Magenta (255,0,255);

即,我想使用类名作为某些预定义颜色的范围。

现在,我在全球范围内的用户文件中执行以下操作:

//user.cpp
#include "Color.h"
static const Color colors[2] = { Color::Red, Color::Magenta };

当我使用颜色[i]时,我发现它们充满了0。 我查了一下,看到第一次调用空构造函数(由于很快就会显示出来的原因没有意义),然后我将空的c'tor更改为:

    Color() : r(200), g(200), b(200) {}

得到了相同的结果。

我尝试将颜色定义为constexpr,如下所示:

    static constexpr Color Red (255, 0, 0);

但它说:     数字常量之前的预期标识符

然后像这样:

    static constexpr Color Red = {255, 0, 0};

就像这样:

    static constexpr Color Red = Color(255, 0, 0);

然后编译失败,因为“'Color'未在此范围内声明”,“Red有不完整的类型”(真的吗?) 所以现在使用空c'tor真的没有意义,而是整个内存用0初始化。

在运行时我可以使用静态const颜色,它可以工作。

我的这种行为甚至定义明确?它取决于编译/链接顺序吗?

我该如何解决?

由于

1 个答案:

答案 0 :(得分:3)

您正在遇到Static Initialization Order Fiasco。听起来colors数组在RedMagenta对象之前被初始化了。

一个解决方案是Construct On First Use Idiom

// Color.h
struct Color {
    int r,g,b;
    Color() : r(0), g(0), b(0) {}
    Color(int r_, int g_, int b_) : r(r_), g(g_), b(b_) {}
    static const Color& Red();
    static const Color& Magenta();
};

// Color.cpp
#include "Color.h"
const Color& Color::Red()
{ static const Color red(255,0,0); return red; }
const Color& Color::Magenta()
{ static const Color magenta(255,0,255); return magenta; }

//user.cpp
#include "Color.h"
static const Color colors[2] = { Color::Red(), Color::Magenta() };