声明与实现.h和.cpp
一般.h放声明, .cpp放定义;
头文件不应该含有非inline函数或对象的定义,定义只能在程序中出现一次,除了inline函数和const常量的定义。
inline
1.如果实现不用inline关键字,要放到.cpp中。 如果放在.h中,两个以上文件包含.h,会出现重复定义错误already defined in。
原因:每个.cpp被编译成一个独立的.obj; 两个以上.cpp包含同一个.h而这个.h中含有实现部分,这个实现部分就被编译到两个.obj中, 此时编译器发现两个.obj中有同一名字的对象,就会出现编译错误。
2.如果实现用inline关键字, 就应该放到.h中。 如果只放到.cpp中相当于外部定义用关键字inline修饰, 则会出现没有定义错误unresolved external symbol。
原因:由内联函数是在调用处展开函数体,由于这个展开过程是在编译时进行的,又由于我们将调用处及类的文件分别单独编译,在编译调用处时不可见,所以出现问题。内联函数只限出现在所编译依赖的目标文件(object file)中。必须在调用处的源码中#include进来, 如#include “.cpp”,当然.cpp中要全部是inline修饰的,不然会出现第一种错误。
即某文件需要用到inline对象时,其必须能够看见该对象的实现(因为它要在编译阶段直接把该对象的实现给包含进来)
3.如果inline和非inline函数同时存在,
a.将inline放在.h中, 非inline放在.cpp中
b.将inline放在一个.cpp中,非inline放在另一个.cpp中, 在引用时包含放inline的那个.cpp文件
const 全局变量
1.常量的定义可以放在头文件中,符号常量可以在一个程序的不同文件中被定义多次(值可以不同)。2.常量可以声明为extern从而不初始化, 这样以后就只能定义一次, 多次在多个文件中定义会提示错误(重复定义)。
这种情况适用于const 的值没有办法在编译时刻计算出来, 必须要到运行时。
如果定义了一个常量却没初始化也没加extern,编译器提示:
error C2734: 'A' : const object must be initialized if not extern
const 类里面的常量
类里面的const常量必须声明为static,因为const的必须初始化,但是类声明中只能给static的初始化,而且在头文件中只能给有序类型(integral)初始化,也可在文本文件中初始化。
别的类型的只能文本文件中初始化,不能在头文件中初始化。
//example.h
class example
{
public:
static const int _size = 20;//ok
static const double _rate; //ok 可以在别的文件初始化
static char name[_size];//不是有序型,不能在.h中初始化
}
但是在vc6中上面的编译不过,vc6中_size不能赋初值,vc6中好多都不支持标准,用gcc编译没问题
模板函数有两种编译方式,
a,包含编译,可以将函数定义放在头文件中,在所有实例化模板函数的文件中包含
b,分开编译,将函数声明放在头文件, 定义放在文本文件中
如果在模板被实例化之前只有函数模板的声明在程序文本文件中可见, 那么, 标准 C++要求用户把函数模板定义标记为 export
export template <typename Type>
Type min (Type t1,Type t2) {/*...*/}
extern
既指定了extern关键字, 又指定了一个显式初始值的全局声明被视为该对象的定义, 会分配空间,该对象的后续定义被标记为错误。
extern实际上就是告诉编译器,被extern的对象你可以在其他的编译单元找到(这也就是全局变量的性质),因此编译器在遇到被extern声明的变量时,它在编译阶段就不会报错(说怎么这个对象只声明没实现啊),在链接阶段它会去其他的编译单元尝试找到该对象的实现,当然如果这时候找不到,会报一个连接错误说找不到该对象。