头文件中的`static`,`extern`,`const`

时间:2012-03-28 13:05:59

标签: c++

//a.h

extern int x1;
static int x2;
int x3;
static const int x4;

class A {
    public:
        static const int x5 = 10;
};
多个a.h文件将包含

.cpp,我的问题是:

1。x1只是一个声明,不是吗?所以它的定义应该在其中一个.cpp文件中完成,对吧?

2. x2是一个定义,对吧?我曾经认为static int也是extern int的声明,但我错了。 x2只会在a.h

中显示

3.如果多个x3文件中包含a.h.cpp将被定义多次,因此x3会导致编译错误,对吧?

4. x4是一个定义,对吧?

5.在A级,x5是一个声明,是的。但是x4呢?

2 个答案:

答案 0 :(得分:10)

  

1.x1只是一个声明,不是吗?所以它的定义应该在其中一个.cpp文件中完成,对吧?

正确

  

2.x2是一个定义,对吗?我以前认为static int也是一个类似于extern int的声明,但我错了。 x2只能在a.h中看到?

每个包含标题的翻译单元中都有一个不同的x2

  

如果a.h包含在多个.cpp文件中,将多次定义3.x3,因此x3将导致编译错误,对吧?

更准确地说,它会导致链接器错误。编译器处理每个转换单元,链接器将它们绑定在一起并检测符号是多次定义的。

  

4.x4是一个定义,对吧?

是的,这是一个定义,但与x2一样,每个翻译单元都有自己的x4(因为static而且因为它是const 内部链接

  

5.在A类中,x5是声明,是的。但是x4呢?

是的,x5只是一个声明(初始化)。可能会出现混淆,因为关键字static在不同的上下文中被重用来表示不同的东西。在x5中,它表示类的属性,而在x4中表示内部链接

这最后一个案例很特别。它是唯一的声明(IIRC)声明可以有一个值,原因是它允许编译器使用包含该标题的所有转换单元中的常量值作为< em>编译时间常数。如果必须为定义提供值,则只有一个翻译单元可以访问该值。该静态成员的定义是:

const int A::x5; // no initialization here

如果会员 odr-used ,您必须提供一个。现在事实是,在大多数情况下,常量不会是 odr-used ,因为编译器将在使用表达式A::x5时替换该值。只有当该成员用作左值时,您才需要定义,例如:

void f( const int & ) {}
int main() {
   f( A::x5 );
}

因为f的参数是引用,A::x5的使用需要左值(注意,const-ness和lvalue / rvalue-ness几乎是正交的) ,这需要在程序中的单个翻译单元中定义成员。

答案 1 :(得分:4)

  1. 正确

  2. 这是一个定义,x2将为0,每个包含标题的翻译单元都有自己的x2副本。

  3. 是的,但它会导致链接器错误,而不是编译器。

  4. 与2.相同,但您无法修改它。

  5. 在课程中,static具有不同的含义。这是合法的,因为x5是const整数类型,也是初始化的。