构造函数排序(全局范围)问题

时间:2015-08-12 12:28:32

标签: c++ constructor global

我有一个构造函数排序问题,我正试图想出创造性的解决方法。

基本上我有一个简单的类Color,它存储RGB颜色信息并允许操纵所述颜色并转换成其他颜色空间(24位,16位,4位,HSV,XYZ,LAB等)。该课程本身运作良好。

我还有一个预定义颜色的库,例如:

namespace Colors {
    const Color Snow                  (255,250,250);
    const Color GhostWhite            (248,248,255);
    const Color WhiteSmoke            (245,245,245);
    const Color Gainsboro             (220,220,220);
    const Color FloralWhite           (255,250,240);
    const Color OldLace               (253,245,230);
    const Color Linen                 (250,240,230);
    const Color AntiqueWhite          (250,235,215);
    const Color PapayaWhip            (255,239,213);
    const Color BlanchedAlmond        (255,235,205);
};

通常在程序中使用时,它们都能正常工作。

当我尝试将构造函数中的库颜色用于另一个对象时,我的问题出现了。没有什么可说的,我使用的库颜色的构造函数已被执行,并且在接收到的另一个类的构造函数之前分配了颜色数据(它执行一些小的预处理来计算一些不同的颜色空间值) Color对象并将其分配给自身内部的存储变量。

例如,Color类有一个构造函数:

Color(const Color &c) {
    setColor(c.getRed(), c.getGreen(), c.getBlue());
}

=运营商:

Color &Color::operator=(const Color &rhs) {
    setColor(rhs.getRed(), rhs.getGreen(), rhs.getBlue());
    return *this;
}

setColor()只是一个小辅助函数,用于存储值并预先计算一些颜色空间替代值。

当我在另一个对象的构造函数中包含一个时,请说:

Color _storeColor;
TestClass(const Color &c) {
    _storeColor = c;
}

或:

Color _storeColor;
TestClass(const Color &c) : _storeColor(c) {}

使用:

TestClass myTest(Colors::WhiteSmoke);

分配的颜色数据(几乎总是)全部0,好像Color类的构造函数还没有运行,我完全得到了。

所以我正在寻找关于如何创建我的预定义颜色库的想法,以便它们可供全局范围内的其他构造函数使用。

顺便提一下,例如:

TestClass myTest(Color(245,245,245));

完美地工作,虽然我不喜欢为数据库提供数百个(并且数百个)或#define个宏,因为这会导致大量不必要的对象重复,我更喜欢保持它始终在重新使用颜色时引用相同的全局实例。

3 个答案:

答案 0 :(得分:5)

正如您所知,C ++标准没有定义调用不同翻译单元中构造函数的顺序。

但是大多数C ++实现通常都提供了指定构造函数初始化顺序的方法,您可以利用这些顺序。[/ p>

例如,gcc具有init_priority属性,您可以将其附加到构造函数并控制构造函数相对于其他构造函数的初始化顺序。这可能是gcc案例中的答案。

检查编译器的文档,以获取有关它在此区域中提供的特定于编译器的功能的更多信息。

对于更可移植的方法,可能可以对POD在命名空间范围内的非平凡类实例之前初始化这一事实做一些事情。有可能利用这个,以便在这里提出一些方法,但我建议首先调查你的编译器的能力。利用编译器为您提供的其他功能没有任何问题。

答案 1 :(得分:3)

您遇到的有时被称为"静态初始化命令惨败"。

处理它的一种方法是使用 Construct On First Use Idiom ,例如,通过将颜色定义更改为getter函数:

const Color & Snow(void) {
    static Color snow(255,250,250);
    return snow;
}

您可以在this article中阅读更多内容。

编辑: 为了避免过多的代码,你可以简单地定义一个帮助宏:

#define DEF_COLOR(name, r, g, b) \
const Color & name(void) { \
    static Color name(r,g,b); \
    return name; \
}

DEF_COLOR(Snow,       255,250,250)
DEF_COLOR(GhostWhite, 248,248,255)
// ...

答案 2 :(得分:1)

如果您可以使用C++11,您也可以尝试安排预处理,以便在编译时计算它并使颜色定义为constexpr

class Color {
    public:
        int m_r, m_g, m_b;
        constexpr Color(int r, int g, int b) : m_r(r), m_g(g), m_b(b) {}
        constexpr Color(Color const& o) : m_r(o.m_r), m_g(o.m_g), m_b(o.m_b) {}
};

constexpr const Color RED = Color(255,0,0);
constexpr const Color BLUE = Color(0,255,0);
constexpr const Color GREEN = Color(0,0,255);

这应该保证在调用其他构造函数之前初始化颜色(在动态初始化之前进行常量初始化)。它还有一个额外的好处,即编译可以在编译时执行预处理,因此它甚至可能更高效(但是,这也意味着如果预处理依赖于仅在运行时可用的值,它将无法工作)。