时间 2020-06-02
原文 https://my.oschina.net/u/4398200/blog/3336507
原文地址:https://blog.csdn.net/qzx9059/article/details/89210571ios
c++中 cpp和hpp
咱们能够将全部东西都放在一个.cpp文件内,编译器会将这个.cpp编译成.obj,即编译单元。一个程序能够由一个编译单元组成,也能够由多个编译单元组成。一个.cpp对应一个.obj,而后将全部的.obj连接起来(经过一个叫连接器的程序),组成一个.exe,即程序。若是一个.cpp要用到另外一个.cpp定义的函数怎么办,只需在这个.cpp中写上它的函数声明。 连接器将全部的obj连接起来,可是若是碰巧有相同的函数或外部变量怎么办?C++能够经过一种叫作连接属性的关键字来限定,某个函数是属于整个程序公用的,仍是只在一个编译单元obj里面使用,这些关键字就是extern(外部连接)和static(内部连接)。让咱们说说.h。其实没有.h,程序也能很好的工做,可是当你发现一个外部连接的函数或外部变量,须要许多分声明,由于只要使用到该函数的单元,就必须写一份声明在那个.cpp里面,若是要修改会很麻烦!!!.h就是为了解决这个问题而诞生的,它包含了这些公共的东西,而后全部须要使用该函数的.cpp,只须要用#include包含进去即可,之后须要修改,只是修改一分内容。#include并非什么申请指令,只是将指定文件的内容,原封不动的拷贝进来。
不是很严格的讲,.h文件作的是类的声明,包括类成员的定义和函数的声明,而.cpp文件作的类成员函数的具体实现(定义)。一个*.h文件和*.cpp文件通常是配对的。在*.cpp文件的第一行通常也是#include".h"文件,其实也至关于把.h文件里的东西复制到*.cpp文件的开头。因此,你所有写在*.cpp文件其实也是同样的。
既然能够直接写cpp,为何还要写hpp?除了编程规范外,还涉及到类一个重要性质,就是封装性。好比如今咱们公司和另外一家软件公司合做,这样就必然要互相提供一些软件的信息(好比一些类,它究竟是要作什么的),但是在提供这些信息的同时咱们又不像让对方知道咱们这些类的具体实现,毕竟这些是咱们公司的算法核心和心血啊。因此这个时候就能够把类的接口(这个类是要作什么的)放在*.h文件中,而具体类的实现放在 .cpp文件。这时候咱们只要给对方公司.h文件就好了。这样既提供了必要的信息,又保护了咱们的核心代码。
1.最表面的机制是:头文件是程序的界面(是代码界面),提供给程序员以 类、模版、函数等一系列的声明,让程序员知道应该怎么调用里面的“东西”。
2.从动态连接库的角度看:头文件提供界面,使得程序员在须要加载一个库函数的时候(这里也仅仅是举简单的例子)查看头文件就知道怎么加载这个动态库内部的函数。
3.从软件的扩展来讲:将头文件做为界面,再去定义它的实现,这样只要保证界面不变(头文件不变),就能够只修改实现文件,而没必要修改其余的实现代码。好比你有一个sort()函数来排序,在一个大程序中,你后来发现这个sort()有更好的算法,因而你只须要去修改函数的实现(修改.cpp文件的sort()函数的代码),其余使用这个函数的地方能够彻底保持不变,这是分割技术的第一个好处
4.从编译的角度看:
全部源文件都是被编译器分别划分单元来分别编译,在编译的过程当中,头文件被嵌入到实现文件里面一块儿做为一个编译单元被编译(实现文件filename.cpp里的#include "filename.h"这一行被替换成filename.h里面的全部内容(实际上会把预处理指令去掉,这才是预处理最本质的做用))。
举一个简单的例子,你定义了sort()函数,在test.h头文件里声明,在test.cpp里定义,这个时候在test.cpp里面#include “test.h”,并定义sort()函数。
你须要在头文件内部写预处理代码
头文件的全部内容,都必须包含在
#ifndef {Filename}
#define {Filename}
12
//{Content of head file} 你的代码写在这里
#endif
这样才能保证头文件被多个其余文件引用(include)时,内部的数据不会被屡次定义而形成错误。
c++中头文件(.h)和源文件(.cpp)都应该写些什么?
头文件(.h):
写类的声明(包括类里面的成员和方法的声明)、函数原型、#define常数等,但通常来讲不写出具体实现。
头文件还能够定义:在编译的时候就已知道其值的cosnt对象和inline 函数。在头文件中定义上述实体,是由于编译器须要它们的定义来产生代码。
源文件(.cpp):
源文件主要写实现头文件中已经声明的那些函数的具体代码。须要注意的是,开头必须#include一下实现的头文件,以及要用到的头文件。那么当你须要用到本身写的头文件中的类时,只须要#include进来就好了。
下面举个最简单的例子来描述一下,咱就求个圆面积。
第1步,创建一个空工程(以在VS2003环境下为例)。
第2步,在头文件的文件夹里新建一个名为Circle.h的头文件,它的内容以下:
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle
{
private:
double r;//半径
public:
Circle();//构造函数
Circle(double R);//构造函数
double Area();//求面积函数
};
#endif
12345678910111213141516
注意到开头结尾的预编译语句。在头文件里,并不写出函数的具体实现。
第3步,要给出Circle类的具体实现,所以,在源文件夹里新建一个Circle.cpp的文件,它的内容以下:
#include "Circle.h"
Circle::Circle()
{
this->r=5.0;
}
Circle::Circle(double R)
{
this->r=R;
}
double Circle:: Area()
{
return 3.14*r*r;
}
123456789101112131415161718
须要注意的是:开头处包含了Circle.h,事实上,只要此cpp文件用到的文件,都要包含进来!这个文件的名字其实不必定要叫Circle.cpp,但很是建议cpp文件与头文件相对应。
最后,咱们建一个main.cpp来测试咱们写的Circle类,它的内容以下:
#include <iostream>
#include "Circle.h"
using namespace std;
int main()
{
Circle c(3);
cout<<"Area="<<c.Area()<<endl;
return 1;
}
注意到开头时有#include "Circle.h"的声明,证实咱们使用到了咱们刚才写的Circle类。
1234567891011
至此,咱们工程的结构为:
注意这里声明与定义的区别:它们最本质的区别是定义只能够出现一次,声明能够出现屡次。声明不分配空间,而定义是要分配空间的。
———————————————— 版权声明:本文为CSDN博主「轻远清清」的原创文章,遵循 CC 4.0 BY-SA
版权协议,转载请附上原文出处连接及本声明。
原文连接:https://blog.csdn.net/qzx9059/article/details/89210571
相关文章
1. .h和.hpp区别
5. c++中的.hpp文件
8. c++中的##和#的区别
9. .h和.cpp文件的区别
10. c++源文件.cpp与.cc区别
• 现实生活中的 XML - XML 教程