【转】C/C++头文件

http://blog.csdn.net/zjf82031913/article/details/7287342

 在头文件中定义了一个变量,若另一个文件包含此文件则会再产生一个相同变量的定义,在linux环境中编译时会发生如

menu.o:(.sbss+0x0): multiple definition of `is_refresh_living_time_thread_created'
main.o:(.sbss+0x0): first defined here

的错误,要在包含该文件的文件中使用此变量应该声明全局变量“extern int is_refresh_living_time_thread_created”,或者叫作“通过extern关键字扩展全局变量is_refresh_living_time_thread_created的作用范围(即扩展到包含该文件的文件中)”;这和头文件中的函数声明不同,因为函数在头文件中仅仅是声明,声明可以有多个,但是无论是函数还是变量定义都只能有一个,否则就会发生重复定义的错误。

      头文件中变量如果没有初始化就是声明;初始化了就是定义,此时被包含之后会发生重复定义的错误。

      并不是所有的变量都能用extern声明,只有全局变量并且没有被static 声明的变量才能声明为extern. 所以如果你不想自己源文件中全局的变量被其他文件引用,你就可以给变量加上static声明.

     

    很多初学者,对变量的定义和声明分不请,只知道有这回事。下面对这两个概念详细说明下:

变量的定义:为变量分配存储空间,同时指明变量的类型和名字。另外变量的初始化,就是在变量的定义出给出值。

变量的声明:它主要向程序声明变量的类型和名字。定义也是声明(这是许多人搞不清楚的地方),那既然变量的定义就是声明,为啥还要再多出来个变量的声明这个概念,直接就用变量的定义不是就可以了?

其实不然,C++中有个关键字是用来声明变量的,它是extern。它声明一个变量却不定义它,即不在给它一个存储空间。

例如:int i;//定义也可以说是声明

extern int i;//这就是单纯的声明

注意:在C++语言中,变量有且只能有一次定义,但是可以声明多次,使用变量前必须定义或声明。

这依然没有说明这个变量声明有什么作用,下面就举个例子说明变量声明的作用

假设我们在文件1.cpp中定义了一个全局变量bufsize,文件1.cpp中当然可以访问它,如果我想在另外一个文件2.cpp中访问这个全局变量,这时候需要在文件2.cpp中声明这个变量。

//1.cpp

int bufsize;

//2.cpp

extern int bufsize;

这说的是非const的全局变量,如果是const的全局变量,如果想要被其他文件访问,需要在定义的时候,加上extern关键字,表示它可以在其他文件被声明使用的,即可以被整个程序(一个程序可能包括多个源文件)访问,否则的话,这个变量只能在它被定义的文件里面被访问,其他文件不能访问。

//1.cpp

extern const int bufsize=10;

//2.cpp

extern const int bufsize;

这时候你也许会问,为什么非const变量定义的时候为什么没有extern?

答:非const变量默认为extern。而const变量如果想要在其他文件里被访问,必须显示的指定它为extern。

看完这个你会对变量的声明和定义有了个新的理解^-^

http://hi.baidu.com/huifeng00/blog/item/977dd653f68507858c54308b.html

 

今天看C++ Primer关于头文件定义的一节,其中说到,头文件应用于声明而不是用于定义。其实,C++标准并没有规定头文件中不能定义 变量,只不过如果在头文件中定义变量,而该头文件又被多次包含的话,会造成变量的重新定义。
        这里还涉及到另一个问题,需要提前说明,即使用预处理器避免多重包含。这里的多重包含指的是同一个文件直接或者间接的包含一个头文件多次,例如a.h包含b.h,a.cpp同时包含a.h和b.h,a.cpp就两次包含了b.h。但由于b.h中具有避免多重包含的措施,a.cpp中还是只包含了b.h一次。而包含的意思其实就是在预处理阶段用被包含文件的内容代替此包含语句。
        回到头文件定义变量的问题上,如果在头文件中定义了变量,避免多重包含的措施只能避免该头文件在同一个编译单元内被包含一次,在不同的编译单元内还是会被多次包含的,这样就造成了变量的重复定义。
        但是也有例外,如果const对象在编译时可以确定其值,可以将其放在头文件中定义。这么做是有原因的——const对象默认情况下是定义该变量的文件的局部变量,这样即使此头文件被多个包含,都不会在包含这些文件中重复定义此变量,所有对于这个const对象的引用全都指向在头文件中定义的对象。如果在const对象定义的时候声明extern,const对象就变得和普通非const对象一样,从而失去此特性(非const对象的默认属性为extern)。
        C++中的很多用法都不是标准C++规定的,但是由于各种原因,已经是约定俗成或是惯常用法,至于原因以及除此之外的其他用法完全可以不必深究,否则很容易钻牛角尖!

 

http://www.cnblogs.com/wendao/archive/2011/12/20/cpp_head_relearning.html

头文件用于声明而不是用于定义
  当设计头文件时,记住定义和声明的区别很重要的。定义只可以出现一次,而声明则可以出现多次。下列语句是一些定义,所以不应该放在头文件里:

1 extern int ival = 10; // initializer, so it's a definition
2 double fica_rate; // no extern, so it's a definition

  虽然ival声明为extern,但是它有初始化式,代表这条语句是一个定义。类似地,fica_rate的声明虽然没有初始化式,但也是一个定义,因为没有关键字extern。同一个程序中有两个以上文件含有上述任一个定义都会导致多重定义链接错误。

  因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。

  对于头文件不应该含有定义这一规则,有三个例外。头文件可以定义类、值在编译时就已知道的const对象和inline函数。

  在头文件中定义这些实体,是因为编译器需要它们的定义(而不是声明)来产生代码。

  一些const对象定义在头文件中
  回想一下,const变量默认时是定义改变量的文件的局部变量。正如我们现在看到的,这样设置默认情况的原因在于允许const变量定义在头文件中。
  在c++中,有些地方需要放置常量表达式。例如,枚举成员的初始化式必须是常量表达式。
  一般来说,常量表达式是编译器在编译时就能够计算出结果的表达式。当const整型变量通过常量表达式自我初始化时,这个const整型变量就可能是常量表达式。而const变量要成为常量表达式,初始化必须为编译器可见。为了能够让多个文件使用相同的常量值,const变量和它的初始化式必须是每个文件都可见的。而要使初始化式可见,一般都把这样的const变量定义在头文件中。那样的话,无论该const变量如何使用,编译器都能够看见器初始化式。
  但是,c++中的任何变量都只能定义一次。定义会分配存储空间,而所有对该变量的使用都关联到同一存储空间。因为const对象默认为定义它文件的局部变量,所以把它们定义放在头文件中是合法的。
  这种行为有一个很重要的含义:当我们在头文件中定义了const变量后,每个包含该头文件的源文件都有了自己的const变量,其名称和值都一样。
  当该const变量是用常量表达式初始化时,可以保证所有的变量都有相同的值。但是在实践中,大部分的编译器在编译时都会用相应的常量表达式替换这些const变量的任何使用。所以,在实践中不会有任何存储空间用于存储用常量表达式初始化的const变量。
  如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义。相反,和其他的变量一样,该const变量应该在一个源文件中定义并初始化。应在头文件中为它添加extern声明,以使其能被多个文件共享。

posted @ 2013-02-07 14:42  chkpk  阅读(389)  评论(0编辑  收藏  举报