变量和函数定义的位置
明确中心思想ODR
通常类的定义是在头文件.h
,类成员函数定义在.cc
,这个.cc
需要include这个头文件
- 下面的定义通常可以对外界封装struct的成员是什么
//public.h
struct sparse_matrix;//forward declaration
typedef struct sparse_matrix * sparse_matrix_t;
sparse_status_t mkl_sparse_s_create_coo( sparse_matrix_t *A,...);//声明库函数
//private.h
struct sparse_matrix{//声明struct内部的东西有啥
//...
};
//private.c
#include<private.h>
sparse_status_t mkl_sparse_s_create_coo( sparse_matrix_t *A,...){//定义库函数
//...
}
//编译库函数成一个库之后,sparse_matrix的声明也被隐藏了起来。而且使用者只知道这个有sparse_matrix的存在而不知道内部成员,
//因此他不能取出成员函数,也不能定义一个sparse_matrix对象,或者将sparse_matrix类型作为返回值类型或者参数,但是可以定义
//指向该结构体的指针并且使用它作为参数和返回值。
- In C++, this is a class declaration:
class Foo;
. This is a class definition:class Foo { void foo(); int bar(const char*);};
。类的定义在多个目标文件中不会冲突!!
class complex;//声明
//c++推荐下面这个定义应当写在头文件,下面这个在声明的同时也定义了一个类
class complex{
double real;
double imag;
public:
complex():real(0),imag(0){};
};
- 类定义和类的成员函数定义不是一回事,通常类声明的时候顺带定义,除非需要forward declaration。这个声明(顺带定义)直接写在头文件。简而言之:类定义请写在头文件,类成员函数定义请写在cpp
全局变量
- 一个全局变量如果是多个单元可见(共享)的,那它必定需要使用
extern
在头文件声明,而在某个源文件中声明一次。 static
变量切勿声明/定义在头文件,除非你真的确定每个单元都需要这样一个独立的static成员(和下面的const全局变量类似)。静态全局变量的全局是针对某个目标文件单元而言的。- 如果const全局变量初始化是常量初始化,那么它应当被放在头文件。(每个include这个头文件的源文件都会有一个拷贝)
成员函数
首先需要强调的是,头文件存在的目的是为了多个源文件共享代码,通常类的定义写在
- 成员函数可以写在类内(即类定义的时候),这时候是内联的,因此多个目标文件不会发生链接时的符号冲突
- 如果成员函数不是定义在类外的,那么必须将其定义在某个源文件里,除非把它声明inline函数(inline函数总是写在头文件)
全局函数
- 非静态的函数声明写在头文件,定义在某个源文件,否则如果定义在头文件,会发生冲突。
- 静态的全局函数声明和应当定义都在源文件,但是某些情况也会将static全局函数定义在头文件,这样每个引用它的单元都有一份自己的拷贝
- 如果函数是内联的,它应当定义在头文件
模板
模板的函数定义需全放在头文件!!
总结:
类型 | 定义 | 声明 |
---|---|---|
静态全局变量 | 源文件 | 源文件 |
非静态全局变量 | 源文件 | 头文件/extern |
const 全局变量,常量初始化 | 头文件 | 头文件 |
const 全局变量,非常量初始化 | 源文件 | 源文件 |
非内联成员函数 | 源文件 | 头文件(类定义的时候) |
内联成员函数 | 头文件(类定义的时候) | - |
静态全局函数 | 源文件 | 源文件 |
普通全局函数 | 源文件 | 头文件 |
模板类和函数 | 头文件 | 头文件 |