2012-03-20 68 views
2

正如我们所知,可以在类结构中初始化整型常量静态成员。当在类结构中使用常量时,例如,它可以用作int数组的大小。 看代码如下:为什么我们必须定义一个在类中初始化的const静态成员

class MyClass{ 
static const int num = 100; 
int elems[num]; 
... 
}; 

但是,我们仍然需要定义类定义之外成员NUM

const int MyClass::num; 

我不知道为什么我们要做这样的。 有人能告诉我为什么吗? 非常感谢。

另外,我写了下面的代码:

#include <iostream> 
using namespace std; 

class MyClass{ 
public: 
MyClass() 
{ 
    cout << "instruct class MyClass!" << endl; 
} 
static const int num = 100; 
int elems[num]; 
}; 

//const int MyClass::num; 

int main() 
{ 
MyClass a; 
const int *b = &(a.num); 
cout << "&(a.num): " << &(a.num) << endl; 
cout << "a.num: " << a.num << endl; 
cout << "*b: " << *b << endl; 
} 

它运行良好的Visual Studio 2008中:

enter image description here

但我已删除的代码,明确成员NUM课外。

我很困惑。有人能为我解释吗?

回答

5

该类中的初始化主要用于获取常量表达式。为此,只有价值很重要。一旦你获得了对象的地址或将其绑定到引用,编译器也需要该对象的位置。这实际上是定义所提供的。

+1

但是编译器可以像处理静态成员模板或内联函数一样处理它,它们都具有多个文件中的定义,但仍然需要一个地址。 – 2012-03-20 11:54:11

+0

@JamesKanze:对于模板的静态成员,您仍然需要一个实际上非常烦人的定义,因为隐式实例化不适用于此。我猜,它可以像内联函数中的静态变量那样工作。我的理解是,这些工作通过创建带有弱符号的函数来实现,并在链接时被丢弃。但是,该语言目前需要定义,尽管编译器可能不会坚持它的存在。 – 2012-03-20 12:03:22

+0

我知道。我只是说在技术上,不要求定义不成问题,因为支持不需要的编译器技术在其他环境中也是必需的。 – 2012-03-20 12:21:16

4

只有当您的代码需要它的地址时,您才需要在类的外部定义静态常量num。这被称为超类定义
如果你的代码不采取num地址,则以一流的初始化将只是正常工作。

理由:

Bjarne的states

“C++要求每个对象都有一个独特的定义,规则将被打破,如果C++允许类是一个需要实体的定义。作为对象存储在内存中。“

请注意,只有static const整数可以被视为编译时间常量。编译器知道整数值不会在任何时候改变,因此它可以应用自己的魔法并应用优化,编译器只是内联这样的类成员,即它们不再存储在内存中,随着存储在内存中的需要被删除,它给出了这样的变量是Bjarne提到的上述规则的例外。

即使static const积分值可以在-类初始化,这些变量取地址是不允许的。如果(并且只有)它有一个不符合类的定义,那么可以使用静态成员的地址,因为编译器需要将它们放在内存中。

+0

最后我明白了。非常感谢!我非常感谢您的回复! – XiaJun 2012-03-21 03:27:34

相关问题