一、头文件(.h):头文件中可以放入的内容有 1.函数原型、2.使用#define或const定义的符号常量、3.结构声明、4.类声明、5.模板声明、6.内联函数
1.函数原型:是指编译器在遇到对特定函数的调用之前,它必须知道函数使用的形参的数量、每个形参的类型以及函数的返回类型
void hanShuYuanXing(); // 函数原型
2.使用#define或const定义的符号常量
(1)#define定义:它用来讲一个标识符(宏名)定义为一个字符串,优点是:方便程序修改
(a) 简单的宏定义:
#define <宏名> <字符串> 例: #define PI 3.1415926
(b) 带参数的宏定义
#define <宏名> ( <参数表>) <宏体> 例: #define A(x) ((x)*(x))
(2)宏替换发生的时机
在讲宏替换发生的时机之前,我们需要先了解代码编译的过程,针对一个项目,有两种说法,第一,一个项目由一个或多个源程序(.cpp)文件组成,第二,有一个项目可以通过编译、链接(由Visual Studio负责做这件事)最终生成一个可执行文件。
这里的编译是一个动作或者是一个阶段,它将源程序文件(.cpp)编译成目标文件(.o或.obj,与操作系统有关),如果项目有多个源程序文件,则会生成多个目标文件,然后编译系统将这些目标文件进行链接,最终生成一个可执行文件(.exe文件)。
编译主要包括预处理、编译、汇编三个过程;
(a)预处理的作用是将宏定义、文件包含、条件编译等特殊代码预先处理,然后再和源程序代码进行上面的编译、汇编等过程。
#define PI 3.1415926 // 宏定义
#include <studio.h> // 文件包含
#ifndef GLOBAL_DEFINITIONS_H // 条件包含(这句话的意思是,如果没有定义GLOBAL_DEFINITIONS_H)
#define GLOBAL_DEFINITIONS_H // 则定义 GLOBAL_DEFINITIONS_H
(b)编译:包括词法分析、语法分析、目标代码生成、优化等
(c)汇编:产生目标文件(.o或.obj)
因此,宏替换发生在预处理阶段。
(3)const定义的符号常量
const double EPSS = 1e-12; //定义一个常量
3.结构声明
struct Thresholds
{
int a;
};
4.类声明
class CommunicateWithFpgaThread : public QObject
{
Q_OBJECT
public:
explicit CommunicateWithFpgaThread(QObject* parent = nullptr);
~CommunicateWithFpgaThread() override;
};
5.模板声明
// 定义函数模板
template<typename T> // template 和typename都是关键字,T是类型,在调用时,自动识别T是什么类型
T funcadd(T a,T b)
{
T addhe = a+b;
return addhe;
}
// 例:
int he = funcAdd(11,12); // 则在调用T funcAdd(T a,T b)函数时,T就会被替换成int
// 如:
int funcadd(int a,int b)
{
int addhe = a+b;
return addhe;
}
6.内联函数(inline)
内联函数的提出:有些函数调用频次很高,会消耗系统资源,为降低因为反复调用函数而产生的系统资源消耗,引入内联函数,其作用是在编译阶段,系统尝试将调用该函数的动作替换为函数的本体(不再进行函数的调用),通过这种方法,来提升程序执行的性能。注:内联函数只是开发者对编译器的一种建议,执不执行,取决权在编译器,无法人为去控制。
inline int myfunc(int testv)
{
return testv * (5 + 4) * testv;
}
二、源文件(.cpp)中存放的内容
1.需要的头文件。
#include<hhhhh.h>
2.全局变量。即头文件中的"extern int 变量名"声明的变量在这儿要进行定义与初始化;
3.只在本文件中使用的变量。即 static 变量类型
4.全局函数的实现。即头文件中的"extern int 函数名"声明的函数要在这儿进行实现。
5.局部函数的实现。即static 变量类型 函数名
总结:.cpp 要实现的内容是头文件的包含、函数的定义、变量的定义与初始化;