我的问题源于Scott Meyers 研究Effective C++.在该书的第二项中,写下如下:
要将常量的范围限制为类,必须使其成为成员,并且为了确保最多只有一个常量副本,必须使其成为静态成员.
这是正确的写.然后立即给出以下示例:
class GamePlayer {
private:
static const int NumTurns = 5;
int scores[NumTurns];
....
};
Run Code Online (Sandbox Code Playgroud)
然后写下以下示例:
你在上面看到的是一个声明,而不是NumTurns的定义.
我的第一个问题是:这个陈述的含义是什么?
紧接着提到以下内容:
通常C++要求您为所使用的任何内容提供定义,但是静态和整数类型的类特定常量(例如 - 整数,字符,bools)是一个例外.只要您不接受他们的地址,您就可以声明它们并在不提供定义的情况下使用它们.如果您确实将类的地址设为常量,或者即使您没有使用该地址,您的编译器也错误地坚持定义,您提供了一个单独的定义,如下所示:
const int GamePlayer::Numturns; //definition of NumTurns
为什么现在它是一个定义而不是声明?
我理解函数上下文中的差异,但在常规变量的上下文中不理解它.此外,有人可以扩展作者的意思
...如果你确实把一个类的地址定为常数,或者如果你的......部分引用了上面引用的段落?
PS:我是C++的新手.
与函数一样,变量可以具有"纯粹声明性"声明和实际定义.你很困惑,因为之前你可能没有遇到过很多纯变量声明.
int i; // Definition
extern int i, j; // (Re)declares i, and declares j
extern int j = 0; // Defines j (confusing, eh?)
Run Code Online (Sandbox Code Playgroud)
正如您习惯使用函数一样,定义是声明,但并非所有声明都是定义.§3.1/ 2读
声明是一个定义,除非它在类定义(9.2,9.4)中声明了静态数据成员,
因此,类内静态数据成员声明永远不会定义它们声明的变量.但是,有时候,变量定义不一定存在.当你可以直接使用它的值而不需要变量运行时存在时就是这种情况.
在技术术语中,只要静态数据成员(或任何实体)不是"使用过的",就不必定义它.所有实体的使用频率在§3.2/ 3中定义:
一种可变
x显示其名称为潜在评估表达ex是ODR使用的由ex除非施加左值到右值转换(4.1),以x产率常量表达式(5.20),其不调用任何非平凡函数,并且如果x是object,ex是表达式的潜在结果集合的元素e,其中左值到右值的转换(4.1)应用于e或者e是丢弃值表达式(第5节).
这看起来很复杂,并且在早期版本的标准中更简单.但是,它大致表示当表达式"立即"访问变量值时,某个表达式不会使用该变量,并且此访问会产生常量表达式.迈尔斯"取其地址"的例子只是众多因素之一.
对于某些类A及其静态数据成员i,
class A {
static const int i = 57; // Declaration, not definition
};
const int A::i; // Definition in namespace scope. Not required per se.
Run Code Online (Sandbox Code Playgroud)
在此声明:
在类接口中初始化的静态
const整型数据成员不是可寻址变量。它们只是其相关值的象征性名称。由于它们不是变量,因此无法确定它们的地址。注意,这不是编译问题,而是链接问题。在类接口中初始化的静态const变量不作为可寻址实体存在。
这里的“可寻址实体”指的是静态const数据类型的“实例”。没有实例,没有地址,即它只是一个声明。
请注意,在源文件中显式定义的静态变量可以正确链接。
class X
{
public:
static int const s_x = 34;
static int const s_y;
};
int const X::s_y = 12;
int main()
{
int const *ip = &X::s_x; // compiles, but fails to link
ip = &X::s_y; // compiles and links correctly
}
Run Code Online (Sandbox Code Playgroud)
...如果您确实获取类常量的地址,或者如果您的 .. 是上面引用的段落的一部分?
这意味着如果这样的成员是 odr 使用的,则仍然需要命名空间范围内的定义,但它不应该具有初始值设定项。
struct X {
const static int n = 1;
};
const int* p = &X::n; // X::n is odr-used
const int X::n; // ... so a definition is necessary
Run Code Online (Sandbox Code Playgroud)