头文件(.hpp)和源文件(.cpp)
1. 基本概念
每个c++程序通常分为两个文件:保存程序的声明(declaration)的头文件和保存程序的实现(implementation)的源文件。源文件就像我们经常见到的简单程序一样,头文件由三部分组成:
- 起始处的版权和版本声明
- 预处理块
- 全局变量和函数的结构声明
例如下面一段c++头文件代码:
//
// computeRec.hpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#ifndef computeRec_hpp
#define computeRec_hpp
#include <stdio.h>
double ComputeRec();
#endif /* computeRec_hpp */
其中最上面用“//”标出的的注释部分就是1,在Xcode环境下,会自动生成;四个“#”标出的部分是预处理,主要目的是为了防止重定义的编译错误,以及包含头文件。唯一一行函数声明中,声明了函数的返回值、函数名以及参数(此例中参数列表为空)。
在编写同名的源文件时,开头必须#include该头文件,并且头文件中声明的函数不必再源文件中全部实现,但是源文件中除了main函数之外的函数最好在头文件中都已经声明过。
2.头文件使用示例
我们知道,自己实现的函数,在调用的地方之前定义实现的,不需要预先声明,否则需要声明。一种比较好的解决方案是把函数的声明都放在头文件中,这样只需要在调用函数的源文件中include该头文件即可。
假设编写一个计算面积的函数,既可以计算圆的面积,也可以计算长方形的面积,由用户选择并给定相应的输入。每个文件如下:
//
// computeRec.hpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#ifndef computeRec_hpp
#define computeRec_hpp
#include <stdio.h>
double ComputeRec();
#endif /* computeRec_hpp */
//
// computeRec.cpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#include "computeRec.hpp"
#include<iostream>
using namespace std;
double ComputeRec(){
double length;
double width;
cout <<"Please enter length and width: \n";
cin >> length >> width;
return length * width;
}
//
// computeCircle.hpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#ifndef computeCircle_hpp
#define computeCircle_hpp
#include <stdio.h>
const double pi = 3.14;
double ComputeCircle();
#endif /* computeCircle_hpp */
//
// computeCircle.cpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#include "computeCircle.hpp"
#include<iostream>
using namespace std;
double ComputeCircle(){
double radias;
cout << "Please enter radias:\n";
cin >> radias;
return pi * radias * radias;
}
//
// main.cpp
// computeArea
//
// Created by Evelyn on 2018/7/30.
// Copyright © 2018年 Evelyn. All rights reserved.
//
#include <iostream>
#include "computeRec.hpp"
#include "computeCircle.hpp"
using namespace std;
int main(int argc, const char * argv[]) {
// insert code here...
int choice;
double area;
cout << "compute rectangular is 1, circle is 2\n";
cin >> choice;
if(choice == 1) area = ComputeRec();
if(choice == 2) area = ComputeCircle();
cout << "area is : " << area;
return 0;
}
我们看到,main函数为了调用函数ComputeRec()
和ComputeCircle()
,只需要include这两个函数对应的头文件即可。
3. 示例程序的Makefile编写
按照程序逻辑自上而下的顺序,我们先写主程序的编译,由于main函数中include另外两个头文件,存在依赖关系,因此主程序需要三个文件共同的汇编代码。main.o单独依赖main.cpp,依次类推,完整的Makefile如下:
computeArea: main.o computeRec.o computeCircle.o
g++ main.o computeRec.o computeCircle.o -o computeArea
main.o: main.cpp
g++ -c main.cpp
computeRec.o: computeRec.cpp computeRec.hpp
g++ -c computeRec.cpp
computeCircle.o: computeCircle.cpp computeCircle.hpp
g++ -c computeCircle.cpp