类的私有积分常量的定义:在头文件或cpp文件中?

时间:2013-08-09 06:55:47

标签: c++

主题已在此处解决(Where to declare/define class scope constants in C++?) 特别是here

我想完全理解,在积分常数的情况下,之间有任何区别:

//In the header
class A {
private:
static const int member = 0; //Declaration and definition
};

//In the header
class A {
private:
static const int member; //Only declaration
};

//In the cpp
const int A::member = 0; //Definition

(据我所知,第二个可能有一个优点,即如果我改变常量的值,我只需要重新编译一个文件)

附带问题:
例如,在访问member的标头中定义的内联方法会发生什么?它只是没有内联吗?如果在一个极端情况下,所有方法都在头文件中定义为内联方法并且所有常量都在cpp文件中定义,会发生什么?

修改

我道歉:我认为没有必要,但我错过了这个成员是静态的事实。我的问题仍然存在,但现在代码是合法的。

3 个答案:

答案 0 :(得分:6)

如果在问题被更改为使其静态之前,它是一个非静态成员,那么它只能在构造函数的初始化列表中或(自2011年起)在成员的声明中初始化。你的第二个例子是不合格的。

如果它是静态的,那么你需要一个定义,如果它是 odr-used :粗略地说,如果你做任何需要它的地址而不仅仅是它的值。如果您只使用该值,那么第一个示例就可以了。但请注意,评论是错误的 - 它只是一个声明,而不是一个定义。

如果确实需要定义,那么您是否在声明或定义中指定了值取决于您。在声明中指定它可以提供更好的优化范围,因为在使用变量时该值始终可用。在定义中指定它可以提供更好的封装,只需要重新编译一个翻译单元。

  

例如,在访问成员的标头中定义的内联方法会发生什么?它只是没有内联吗?

没有理由访问另一个翻译单元中定义的数据对象会阻止内联函数。

答案 1 :(得分:3)

这是数据隐藏的问题。是否要公开内部类字段。如果您要发布类库并希望隐藏实现细节,那么最好在界面中显示尽可能少的实体,然后甚至私有字段member的声明太多。

我只是将此值声明为.cpp文件中的静态变量。

答案 2 :(得分:2)

需要考虑两个观点,即可见性和寻址。

请注意,这两个是正交的,因为您实际上可以将变量声明为已初始化并仍然在转换单元中定义它,因此它在内存中具有有效地址。

<强>可见性

可见性会影响变量的使用,并会产生一些技术影响。

要在模板代码中用作非类型模板参数,该值必须在使用时可见。此外,在C ++ 11中,这可能是constexpr用法所必需的。否则,必要该值是可见的。

从技术上讲,可见值可以触发编译器的优化。例如,if (A::member)非常简单,因此可以省略测试。这通常称为常量传播。虽然这看起来似乎是一件好事,但乍一看,却产生了深远的影响:头文件的所有客户端都可能依赖于此值,因此对此值的任何更改都意味着它们应该重新编译。如果将此标头作为共享库的一部分提供,则意味着更改此值会破坏ABI。

<强>寻址

这里的规则很简单:如果变量可以被寻址(通过指针或引用传递),那么它需要驻留在内存中的某个位置。这需要一个翻译单元中的定义