函数的声明与定义
函数声明:
函数声明的作用是把函数的名字、类型以及形参类型、个数和顺序通知编译系统,以便在调用该函数时系统会按此进行对照检查(例如函数名是否正确,实参与形参的类型和个数是否一致)。
void add(int, int);
函数定义:
函数定义是指对函数功能的确立,包括指定函数名,函数值类型、形参类型、函数体等,它是一个完整的、独立的函数单位。其中包含了函数功能的实现代码。
void add(int a, int b) {
return a + b;
}
一般我们写代码时会将函数的声明写在主程序之前,而将函数的定义写在主程序的后面,这样会增加代码的可读性。尤其当封装的函数较多较长时,读者可以跳过函数的定义直接阅读主函数,有时也可通过灵活的函数命名使读者可以大致了解函数的功能。
void add(int, int);
int main() {
add(1, 2);
return 0;
}
void add(int a, int b) {
return a + b;
}
如果函数声明出现问题,将会在编译阶段就会发生如下的报错信息。
>> g++ -c add.c
error: ‘add’ was not declared in this scope add(1, 2);
如果函数定义出现问题,在没有语法错误的情况下,会通过编译过程,但会在链接过程报错。
>> g++ -c add.c #可以顺利通过编译生成add.o文件
>> g++ add.o #链接对象文件
error: 对‘add(int, int)’未定义的引用
下图是一个源程序最终变为可执行程序所要经过的步骤。
预处理阶段会将所有引入的头文件和定义的宏进行展开,编译阶段检查代码是否存在语法错误,如果函数未声明,则会在编译阶段报错。每一个源程序最终会生成一个对象文件,最终需要将所有的对象文件进行链接,如果函数未定义,则在链接的过程中,函数在调用的时候找不到函数定义,则会发生报错。
工程文件规范
一般简单的程序通过上面介绍的代码格式是没有问题的。但当代码量很大时,比如有很多人共同开发一个项目,就需要每个人有自己的负责部分,并在最后将所有人的部分结合形成一个完整的可以提供某些功能的模块。这就需要将函数的声明与定义分开处理。
一般分为以下几个步骤
- 将所有的函数声明放到头文件(.h)中
打开一个头文件,通常有以下几条语句
#ifndef _文件名_H//如果打开时没有特殊的宏的话,则视为第一次包含,执行下面内容
#define _文件名_H//如果当前没有定义该宏,则定义这个宏
//在这里插入函数的声明
#endif
//这段代码的目的是避免在一次编译中的头文件被重复包含
- 将所有的函数定义放到相应源文件(.cpp)中
这里最好是将一个函数定义的源文件与对应的头文件命名相同,便于清晰的了解头文件和源文件的对应关系。
源文件(包括主函数文件)中需要包含文件中使用函数所在的头文件
#include <***.h>//是在系统包含的路径中进行查找
#include "***.h"//是在当前目录中进行查找
//include的作用实际上是将.h文件中的内容拷贝一份
如果想把自己的.h文件也可以使用<>引入,只需要将自己的头文件所在的目录添加到系统查找的目录中去,编译时需要做如下处理。
g++ -I头文件所在目录
g++ -I./ #头文件在当前目录的情况下,将当前目录添加到系统头文件的查找路径当中
- 编译所有的源文件生成对象文件
g++ -c -I./ *.cpp
- 链接所有的对象文件
g++ *.o
- 生成可执行文件a.out
./a.out
静态链接库
静态链接库的作用是把函数的定义和声明分开处理,把所有的定义打成一个包。
ar -r libhello.a *.o #生成静态链接库libhello.a,这个名字可以任意取,注意前缀为lib即可
- 在项目文件夹下创建一个
module
文件夹,将所有的.h、.cpp、.o文件移动到该文件夹下;
mkdir module
mv header* moudle/ #假设所有的文件(除主程序)都以header开头
- 在module文件夹下创建
include
文件夹,将所有的.h文件放在该文件夹下
mkdir include
mv header*.h include/
- 在module文件夹下创建
src
文件夹,将所有的.cpp文件移动到该文件夹下
mkdir src
mv header*.cpp src/
- 在module文件夹下创建
lib
文件夹,准备将静态链接库生成在该文件夹下
mkdir lib
- 生成静态链接库
进入src目录下,编译所有的.cpp文件生成相应对象文件
g++ -I../include *.cpp
打包所有的对象文件生成静态链接库libhello.a
ar -r libhello.a *.o
将静态链接库移动到lib
文件夹下
cd ../lib/
下面的目录结构更直观的表现了以上的操作流程:
提供给他人进行使用时,只需要提供静态链接库(lib文件夹)和头文件(include文件夹)即可。
写主程序时只需要引入相应的头文件,然后执行下面的命令:
g++ -I./module/include -L ./module/lib main.cpp -l hello
#-L添加静态链接库路径 -l后面加具体静态链接库名
./a.out
End |