当前课程知识点:面向对象程序设计(C++) > 第一讲 课程简介与编程环境 > 1.1 编程环境与工具 > 源程序拆分
大家刚才看到的呢
是一个非常简单的程序
它的编译链接的过程
当然了这个程序
它只是算了一个三加四对吧
它其实没有什么太复杂的功能
如果我们要做的事情很复杂
那可想而知源代码一定会越来越长
比方说就像大家现在看到的这个代码一样
它达到了两千多行那这个时候
一个两千多行或者更多上万行的这种代码
你要用一个源代码文件
去对它进行管理的话
是非常的不方便的
而且也不便于多人的协作
那怎么办呢
下面我们这个内容就是来告诉大家
当一个源代码变得越来越复杂的时候
我们应该怎么来处理它
首先源代码长了
很简单把它拆开
所以就像这个大家看到的这个样子
我们有一个EX1.cpp
如果它很复杂
我们想把它拆成多个cpp
利用这种形式使得每一个源代码
每一个cpp 文件它都比较短小
这样的话也便于维护也便于交流
像这个例子里头我们看到了
把EX1.cpp 拆成了part1part2part3三个文件
然后呢它们能够合在一起去编译
最后能够输出来跟你单独一个文件
去编译链接一样的这种可执行代码
我们给大家一个例子
这个例子当然是
用来示意这个源代码 拆分的
所以呢代码本身并不是达到几千行那么大
我们只是为了展示怎么来拆这个文件
可以看到在这个文件里头
前面有两个这个包含的头文件的
这两个两行代码
接着呢是一个红颜色的
定义了一个ADD的这样的一个函数
那么它把两个参数进行了相加
下面是main函数
当然main 函数的内容我们现在呢
不用太去管它
我们只需要知道在这main函数里头
它调用了这个ADD这个函数
就这么一个功能
那么对于这样的一个程序
一般来讲我们怎么去拆分它呢
通常是把这个辅助函数把它剥离出来
就像我们在屏幕上看到的这个样子
把这个源代码拆成了多个cpp
其中一个cpp是包含的这个ADD
这种辅助函数的定义
另外的一个cpp呢是包含了main函数
就是主函数
那么这样的话呢就会出现两个cpp
有了这两个cpp是不是问题就完了呢
不是的
我们为了方便后续的课程的学习
和我们代码的这种管理
我们下面要介绍的一个办法是使用头文件
来把函数的声明和函数的定义给它分开
我们在程序设计基础
这门慕课课里头已经介绍过
函数的声明和定义是两个不同的东西
那么为了去把源代码进行拆分
我们通常呢需要给出来一个头文件
里头包括了所有你想包括进来的
函数的头就是它的声明
然后函数的实现 也就是函数的函数体
是放在另外的cpp里头
这样呢就把刚才的这个例子里头
我们看到的ADD这个相加的这个函数
那个cpp就进一步拆分成两个
一个呢我们把它命名为这个func.h
另外一个呢叫func.cpp
它们分别是对函数的声明和它的定义
就像下面大家看到的这个样子
在func.h里头实际上就是函数的头这么一行
在func.cpp里头呢就是这个函数的定义
那么有的时候呢有一些
这种其他的结构啊或者其他的东西
需要包含进来所以一般来讲呢
在func.cpp里头会写上include "func.h"
这样的一个预编译的这种指令
由于这个头文件是我们自己编写的
所以通常这个头文件的名字
是用双引号把它引起来的
像我们以前用的iostream
那是系统编译环境提供的
在那个里头我们一般是用尖括号
把这个iostream把它括起来的
所以这两者之间有个差别
这就是说这两者之间更细微的区别
到底是什么
我想建议大家在网上去搜索一下
我们课上就不去说了
好下面这部分是一个main.cpp
就是剥离开这个ADD的头
它的定义之后
我们的主程序怎么写呢
可以看到在这里头也多了一行 include
同样是用双引号引起来的func.h
也就是在告诉编译器
我这里头有一个头文件它包含进来
那么在这个文件里头呢定义了
在这个头文件里头声明了ADD这个函数
至于说这个ADD它的函数的实现体在哪里
那当然从这个里头是看不出来的
我们是在编译链接的时候
才会告诉编译器它的这个定义在哪里
如果你不给出定义的话它会出编译错误
那好在我们使用头文件的时候呢
有一个注意事项
有的时候在头文件里会定义一些别的东西
那这个时候你在包含它的时候
很容易发生一个问题
就是当你重复包含的时候
有的时候会出现编译错误
那既然这种可能性存在
我们在编程序的时候就要把它防止掉
所以无论你现在写的代码
当他头文件被重复包含的时候
会不会出编译错误
你都应该按照我们下面要讲的这个办法
来做一个防范
因为将来你编程的环境
跟人协作的时候
问题任务更复杂的时候
说不定哪天就碰到这样的一个问题
所以我们大家通常就会用下面的办法
来做一种预防性的
就是防止它重复包含所导致的编译错误
它的做法是这样子的
把我们的这个func.h
本来我们这里头只有一行
函数的这种声明
在它的这个文件的最前面
和这个文件的最后面去增加一些内容
就像这个示例里头大家看到的
是一个预条件编译的一个指令
叫#ifndef FUNC_H 一个字符串
这个字符串里头只能用字母
这个这跟变量的定义是一样的
里头不能包含这个点
不能用数字开头等等
不能用特殊字符
然后第二行#define同样的一个符号
就是说如果没有定义这个func.h这样的一个符号
那么就定义它
然后才出现你的这个头文件的这种声明
这个函数头的声明
int ADD int a int b这样的一个声明
然后在文件的最末了
加上井号ADDif
有了这样的处理之后呢
当你多次包含func.h
它就不会出现编译错误
-1.0 课程定位、教学内容
-1.0 课程定位、教学内容--作业
-1.1 编程环境与工具
--源程序拆分
-1.2 main函数的命令行参数
-作业一--作业
-2.1 变量定义
--变量定义
-2.2 变量的初始化、类型推导与基于范围的循环
-2.3 函数重载
--函数重载
-2.4 函数参数的缺省值与追踪返回类型的函数
-2.5 类的定义
--类的定义
-2.6 类成员的访问权限与友元
-第二讲 基础语法(1)--作业二
-3.1 构造函数析构函数
--构造函数析构函数
-3.2 赋值运算符重载
--赋值运算符重载
-3.3 流运算符重载
--流运算符重载
-3.4 函数运算符重载
--函数运算符重载
-3.5 下标运算符与自增减运算符重载
-3.6 静态成员与常量成员
-3.7 对象组合
--对象组合
-3.8 移动构造函数
--Video
--Video
-3.9 default修饰符
--Video
-第三讲 基础语法(2)--作业三
-4.1 继承
--Video
-4.2 函数重写
--Video
-4.3 虚函数
--Video
--Video
-4.4 自动类型转换
--Video
-4.5 禁止自动类型转换
--Video
-4.6 强制类型转换
--Video
-4.7 函数模板
--Video
-4.8 类模板
--Video
-4.9 成员函数模板
--Video
-4.10 模板特化
--Video
-作业四--作业
-5.0 引言
--Video
-5.1 从FOP到OOP
--Video
-5.2 对象在哪里
--Video
-5.3 接口在哪儿
--Video
-5.4 实现接口
--Video
-5.5 变与不变:多态的威力
--Video
-6.0 引言
--讨论
-6.1 从负载监视器的设计开始
-6.2 接口的分离与单一责任原则
-6.3 委托与接口的进一步分解
-6.4 分离不同层面的可变性
-7.0 引言
--Video
-7.1 迭代器
--Video
-7.2 迭代器的实现
--Video
-7.3 迭代器与模板
--Video
-7.4 算法与数据的解耦
--Video
-7.5 抽象结构与类模板
--Video
-7.6 函数对象与算法分解
--Video
-7.7 基于模板的策略模式
--Video
-8.0 引言
--Video
-8.1 已有资源的组合
--Video
-8.2 适当引入接口
--Video
-8.3 接口不变时的功能变化
--Video
-8.4 装饰
--Video
-8.5 责任的传递与责任链
--Video
-8.X 小结
--Video
-9.0 引言
--Video
-9.1 通过封装增加隔离、应对变化
--Video
--Video
-9.2 增加抽象层,应对变化
--Video
--Video
-9.3 相互关联对象的创建
--Video
-9.4 示例:自动组卷系统设计
--Video
-9.5 设计思路(上)
--Video
-9.6 设计思路(中)
--Video
-9.7 设计思路(下)
--Video
-9.X 小结
--Video
-课程总结
--Video
-期末考试--作业