我终于把C++多文件编程理解透彻了
文章目录
- 1、文件类型
- 1.1、头文件
- 1.2、cpp源文件
- 2、多文件的编译
稍微大一点的项目都不会是单个文件的,多文件的好处实在太多,模块开发、分工协作、代码复用、结构清晰、模块更新…不细扯,直接梳理一下C++源代码的文件类型、多文件编译。
1、文件类型
C++程序一般分三类文件:
- 头文件( .h )。放置各种声明,用于被cpp文件包含。
- 模块文件(.cpp)。放置一些函数定义,也称为功能模块。
- 主程序文件(.cpp)。包含main()的文件,程序入口,调用模块文件实现的方法。
1.1、头文件
头文件的存在是为了联系多个源文件,是源文件之间的接口。C++与C一样,要求先声明后使用,可是编译的时候是单文件编译的。看一个没有头文件的例子。
//main.cpp
void fun(); //必须先声明,不然调用出错
int main(){fun(); // 调用fun
}
//fun.cpp
#include <iostream>
void fun(){std::cout<<"This is fun."<<std::endl;
}
使用命令g++ main.cpp fun.cpp
编译两个文件之后是可以正常运行的。这里你需要知道一点C++编译过程原理:C++把每个文件单独编译出来,再通过链接把编译出来的多个文件组成一个可执行程序。编译的时候只检查函数声明,只要该文件能在之前声明过函数就能编译成功。函数定义是在链接阶段检查的,而链接是多文件共同参与的。上例中,main.cpp必须先声明函数fun()才能通过编译, 尽管没有在main.cpp中定义,但在链接的时候发现fun.cpp定义了该函数,程序正确。
但是,每次使用其它文件的函数前都要自己先声明显然很繁琐也容易出错。所以,我们把声明类语句放到一类文件里,称之“头文件”,如果你需要使用到某个函数,就把它所在的头文件包含进来,头文件的内容会在编译前被粘贴到源文件中,这样在编译的时候就能正常通过了。看使用了头文件之后的例子。
//main.cpp
#include "header.h"
int main(){fun();
}//header.h
#ifndef HEADER_H
#define HEADER_H
void fun();
#endif//fun.cpp
#include <iostream>
void fun(){std::cout<<"This is fun."<<std::endl;
}
头文件的内容一般都会使用条件编译预处理语句(如上)包住,防止因为依赖关系多次被包含。
既然知道头文件的作用,那哪些东西应该放在头文件?哪些不能放在头文件?很好理解,如果这部分需要复制给每个相关的cpp,就把它放在头文件,如果被多个cpp复制之后,可能导致它们在链接过程出错,就不要放在头文件。 一 一来看:
- 函数声明:显然应该放在头文件中,前面很清楚。
- 类定义、结构定义:用函数定义的逻辑想,似乎不能放在头文件中。但它应该放在头文件。第一,每个cpp文件应该有一个定义,在编译的时候编译器才知道怎么为对象分配空间。其次,类型定义不会在内存上分配空间。
- 模板函数:编译器必须在编译的时候根据函数模板实例化对应的函数,所以应该放在头文件。
- 内联函数:编译期间被插到调用位置,所以也要放在头文件。
- 函数定义:不要!C++规定一个程序同签名的函数只能有一个定义。如果你把函数定义放在头文件件,并且同一个程序的多个cpp文件包含了该头文件,这样,在链接的时候会发现多个定义版本,链接报错。
- 变量定义:不要!与上面类似,被多个文件包含的时候会出现多次定义同一个变量,链接错误。但是,static变量和extern变量可以,以及宏定义的常量,因为这些在多个文件出现并不会出错。
1.2、cpp源文件
把头文件的东西抽离出去之后,剩下的就可以放在cpp文件了。在cpp文件上,除了需要include对应的头文件之外,没有什么变化。
尽管都是cpp文件,还是有必要理解成模块文件和主程序文件,二者类似功能的提供者和使用者,在实际中,也常常由不同的人开发。
2、多文件的编译
如果是使用Windows下的集成开发环境的,大可直接Build,一键搞定,但你对这个过程的理解就可能差点。所以我以linux上为例,最简单的多文件编译命令:
g++ main.cpp fun.cpp -o out #列举所有要编译的文件
也可以单独编译成 .o文件之后再链接:
g++ -c main.cpp -o main.o
g++ -c fun.cpp -o fun.o
g++ main.o fun.o -o out
第二种是不是引起了你的疑惑——这么麻烦?可是,这种方式提供了一个优点——模块编译更新。你只需要编译你修改过的文件,再跟其他的链接,无需再次对整个项目编译。
在实际的项目中,项目文件可不是小数目,无论上面的那种方式,你都需要一一列出文件,不实际。IDE工具自然没有这种烦恼。不过Linux也会使用Makefile进行项目管理,实现自动编译。行了,又多了一样要学。
我终于把C++多文件编程理解透彻了相关推荐
- C语言模块化开发,深入多文件编程
目录 文章目录 目录 多文件编程 项目分割 避免命名冲突 项目生成的过程 预处理 编译 汇编 链接 语言发展的过程 机器语言 汇编语言 C语言 高级语言 编译的本质 目标文件里藏着什么 可执行文件 链 ...
- linux文件编程(open、write、read、creat、lseek函数)
文件编程内容比较多,如文件系统原理及访问机制文件在内核中的管理机制,什么是文件信息节点iNode.文件共享.文件权限.各种用户对其权限等等.以下主要记录如何用代码操作文件,实现文件的创建.打开.编辑等 ...
- c语言const常量用法,C++ const常量在多文件编程中的3种用法
<C++多文件编程是什么>一节提到,多文件编程中代码的划分原则是:将变量.函数或者类的声明部分存放在 .h 文件,对应的实现部分放在 .cpp 文件中.值得一提得是,此规律适用于大部分场景 ...
- Visual C# 资源文件编程--创建资源文件
资源文件顾名思义就是存放资源的文件.资源文件在程序设计中有着自身独特的优势,他独立于源程序,这样资源文件就可以被多个程序使用.同时在程序设计的时候,有时出于安全或者其他方面因素的考虑,把重要东西存放在 ...
- 手机c语言多文件编程,C语言多文件编程
今天,IT培训网小编为大家总结的是C语言,C语言多模块开发(多文件编程). 目前为止,我们编写的大部分C语言程序都只包含一个源文件,没有将代码分散到多个模块中,对于只有几百行的小程序来说这或许可以接受 ...
- [Linux系统编程]_文件编程(一)
嵌入式之路,贵在日常点滴 ---阿杰在线送代码 目录 一.系统调用 1.1 什么是系统调用 1.2 什么是库函数 1.3 将hello写入到文件1.txt流程 1.4 为什么要有缓冲区(补充) 1.5 ...
- Linux实验---多文件编程Makefile实验二
多文件编程Makefile实验指导书 一 实验题目: 二 实验目的 三 实验内容 四 实验步骤 五 实验结果 六.总结 一 实验题目: 多文件编程Makefile 二 实验目的 (1) 熟悉Linux ...
- Linux基础之文件编程
文件编程篇 一:文件的打开及创建 二:文件写入操作 三:文件读取操作和文件光标移动操作 四:文件打开创建的补充 五:文件操作原理概述 六:文件操作小应用之实现cp指令 七:文件编程小应用之修改程序的配 ...
- linux应用程序接收文件,Linux应用程序学习之文件编程
Linux应用程序学习之文件系统调用函数编程 上一篇我们了解了Linux系统下函数库的设计方法,这一章我们就来学习一下linux系统下常用的文件操作函数,在进行系统文件操作函数介绍前,我们首先要明白一 ...
最新文章
- python从字符串解析方法名
- SAP Spartacus Page Layout学习笔记
- 首批国家应用数学中心名单公布,哪些高校获批?
- Flutter BottomNavigationBar 三分钟实现一个常用APP首页底部导航菜单栏
- .Net页面缓存OutPutCache详解
- visual studio 设计器不显示_嫦娥上升器为什么不设计成月球勘测器?
- 指针变量的所占字节数大小确定
- MySQL的连接字符串 concat、concat_ws、group_concat、repeat()函数用法
- Mac更换JDK版本
- 谷歌浏览器不能上网的解决办法之一
- C++刷题: 逆波兰表达式(力扣150题)
- 80004005错误代码_0x80004005,小编教你解决0x80004005错误代码的方法
- 爬虫日记(23):用scrapy快速地爬取蜂鸟网图片
- 通过网线连接两台主机
- PTA实验4-1-3 找出最小值 (20分) 本题要求编写程序,找出给定一系列整数中的最小值。
- java idea导入ecli项目
- 2.1 SSD算法理论
- Git本地版本回退与远端版本回退(回滚)
- ruby on rails win下安装
- 妥妥解决MySqL中文乱码问题,就这么任性