C++PrimerPlus 学习笔记 | 第九章 内存模型和命名空间 |1.单独编译

单独编译

C++允许甚至鼓励程序员将组件函数放到独立的文件中,在C++中可以单独编译这些文件,然后将它们链接成可执行的程序。(一般来说C++编译器及编译程序也管理链接器)

但是问题来了到底如何划分一个程序放到多个文件中,难道就是简单的讲他们分开吗?假如一个文件中包含了一份结构定义,那么如果在另一个文件也想使用这个定义,那就必须要包含结构声明,那随着使用的文件数量增多,就会出现相当声明,万一想要修改声明,难道要修改这么多份吗?所以与其将其这么多声明单独的放到文件中,不如放在头文件中(.h),然后在每一份源码包含这一份头文件,这样修改声明的时候只需要在头文件做一次修改就可以了。

所以可以将原来的程序分成三部分

  1. 头文件:包含结构声明和使用这些结构的函数的原型
  2. 源代码文件:包含与结构相关的函数的代码
  3. 源代码文件:包含调用与结构相关的函数的代码

请不要将包含函数定义或者变量声明放到头文件中,对于简单的可能可行,但是对于两份文件包含同一份头文件,会导致程序包含两个该程序的定义,除非函数是内联的否则将出错。


头文件应该包含的内容:

  1. 函数原型
  2. 使用 #define 或者 const 定义的符号常量
  3. 结构声明
  4. 类声明
  5. 模版声明
  6. 内联函数

将结构声明放在头文件是可行的,因为它们不变量,而是只是在源文件中创建结构时,告诉编译器如何创建该结构。

模版声明不是将被编译的代码,他只是告诉编译器如何生成与源代码中函数调用相匹配的函数定义。

被声明位const的数据和内联函数具有特殊的属性,被放在头文件不会引起问题


在包含自己的头文件时候应该是用 “” 而不是 <>

在使用指令编译的时候只需要添加源代码文件而不需要头文件,这是因为 #include 会自动添加头文件

请不要使用 #include 来包含源代码文件,这样做会导致多重声明


头文件管理

在同一个文件中只能将同一个头文件包含一次。但是很可能在不知情的情况包含了多次,例如可能使用另外一个头文件的头文件。有一种C/C++标准技术可以避免多次包含同一头文件,他是基于预处理器编译指令#ifndef(if not define),下面的代码意味着只有没有定义过 POLAR_H 才执行 if 和 endif 中间的语句

#ifndef POLAR_H // 如果没有定义 POLAR_H 执行
#define POLAR_H // 定义 POLAR_H 阻止第二次运行

// ... 

#endif //POLAR_H

编译器首次晕倒该头文件,名称 POLAR_H 没有定义 (我们通过文件名+下划线+ H + 下划线来统一命名防止重复).这种情况编译器将会编译中间的代码同时定义 POLAR_H ,如果在另外代码处再次包含头文件,编译器会发现 POLAR_H 已经被定义从而跳过编译。这种方法虽然不能防止头文件被包含两次,而知识让他忽略第一次包含以外所有的内容。大多数C/C++头文件都是用这种防护策略,不然定义多个结构两次可能导致错误。

在IDE中往往会自动建立这种防护,而无需我们手工写入


9.1 & 9.2 & 9.3 多文件编程实例

// coordin.h
#ifndef COORDIN_H
#define COORDIN_H
// structures template
struct polar
{
    double distance;
    double angle;
};
struct rect
{
    double x;
    double y;
};
// prototypes
polar rect_to_polar(const rect&);
void show_polar(const polar&);
#endif //COORDIN_H
// file1.cpp
#include <iostream>
#include "coordin.h"
using namespace std;

int main()
{
    rect rplace;
    polar pplace;

    cout << "Enter x and y value:" << endl;
    while (cin >> rplace.x >> rplace.y){
        pplace = rect_to_polar(rplace);
        show_polar(pplace);
        cout << "Next 2 number:" << endl;
    }
    return 0;
}
// file2.cpp
#include <iostream>
#include <cmath>
#include "coordin.h"
using namespace std;

// convert rect to polar
polar rect_to_polar(const rect & xypos)
{
    polar answer;

    answer.distance = sqrt(pow(xypos.x, 2) + pow(xypos.y, 2));
    answer.angle = atan2(xypos.y, xypos.x);

    return answer;
}

void show_polar(const polar & dapos)
{
    const double Rad_to_deg = 57.29577951;

    cout << "distance = " << dapos.distance << endl;
    cout << "angle = " << dapos.angle * Rad_to_deg << " degrees" << endl;
}
# 使用 g++ 编译 不需要包含头文件
g++ -std=c++11 file1.cpp file2.cpp -o "xytpolar"

多两个源代码文件和新的头文件一起进行编译和链接,将生成一个可执行文件。

虽然我们讨论的是根据文件单独进行编译,但是为了保证通用性,C++标准使用了术语翻译单元,而不是文件。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值