C++中.cpp和.hpp的区别

摘要:
如果.cpp需要另一个定义的函数。cpp,只需用这个编写它的函数声明。cpp。严格来说。h文件进行类声明,包括类成员定义和函数声明,而。cpp文件对类成员函数进行了特定的实现(定义)。A*。h文件和一个*。cpp文件通常是成对的。*的第一行。cpp文件也是#include“.h”文件。实际上,它相当于复制的内容。h文件添加到*的开头。cpp文件。C++中的头文件(.h)和源文件应该写什么?此文件的名称不必是Circle。cpp,但强烈建议cpp文件与头文件相对应。

原文地址:https://blog.csdn.net/qzx9059/article/details/89210571

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

免责声明:文章转载自《C++中.cpp和.hpp的区别》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Prometheus告警发送时间详解[转]iOS高级调试&amp;amp;逆向技术-汇编寄存器调用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

实现socket非阻塞设置

刚开始学习,难免有些疏漏之处,请各位多多指教。 程序亲测可以使用。废话不多说。 网络IO模型分为阻塞IO、非阻塞IO、异步IO、IO复用、信号驱动IO。 阻塞IO: 有数据时,直接读;没有数据时,等待读。 非阻塞IO: 无论内核有没有数据都读。 以下是程序: 1. serevr.c 1 #include <stdio.h> 2 #include...

Ubuntu13.04使用Mesa

3年前写过一些关于如何使用Mesa的文章,如今再试。有些东西已经变了。 首先安装: sudo apt-get install libgl1-mesa-dev sudo apt-get install libglu1-mesa-dev sudo apt-get install freeglut3-dev 现在不用NetBeans了,用CMake创建工程。...

线程.Qt更新界面

1、信号&槽 机制 即可  ZC:个人暂时 测试下来,类似是 PostMessage(...)的方式:   a、是在各自的线程中执行代码,   b、调用 emit不耗时(指的意思是 像调用PostMessage(...)一样 扔完就算,具体 slot中需要执行多久 不关“emit ???()”的事) 2、测试代码:  2.1、h #ifndef M...

C++访问WebService gSoap方式

一、 gSOAP访问WebService 1. 下载gSOAP gSOAP 2.7.17 版下载地址http://sourceforge.net/projects/gsoap2/) 2. 安装gSOAP 解压下载的gsoap_2.7.17.zip,假设该路径为F:WebServicegsoap-2.7 3. 通过WSDL生成C++头文件 3.1、通...

Linux头文件和库文件添加环境变量与GCC编译器添加INCLUDE与LIB环境变量

  对所有用户有效在/etc/profile增加以下内容。只对当前用户有效在Home目录下的 .bashrc或.bash_profile里增加下面的内容: (注意:等号前面不要加空格,否则可能出现 command not found) #在PATH中找到可执行文件程序的路径。 export PATH =$PATH:$HOME/bin #gcc找到头文件的...

cmake编译多个文件

demo.h #ifndef UNTITLED_HEADER_DEMO_H #define UNTITLED_HEADER_DEMO_H void printHello(char *name); #endif //UNTITLED_HEADER_DEMO_H demo.c // // Created by gxf on 2020/2/6. // #i...