前言:最近使用opencv,需要把c++复习下,发现改了好多这几年,随记录下这些概念和使用方法
作用:将可以被多个.cpp文件使用的函数或方法统一封装在一个文件中,当其他.cpp文件需要使用这个变量或函数时,通过#include将其包含进来就可以。
原因:这里涉及到c++的编译模式,头文件是不被编译的,只有源文件(.CPP)文件才会被编译,当然也可以说头文件和包含他的源文件一起编译,所以为了方便这些函数的多次复用和契合c++的分别编译,就可以将这些变量和函数放在.h文件中,谁需要用谁就#include下就可以了。
使用:头文件中写些变量声明了,函数声明了,类的定义了之类的,具体的可以查看文末引用的文献,那里面讲的详细。
引用:系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。用户自定义的头文件用双引号括起来,编译器首先会在用户目录下查找,然后再到c++安装目录下查找,最后在系统文件中查找。
.CPP文件,c语言中是.c文件,称为c++源文件,里面放的都是c++的源代码。.cpp文件里面的东西都是相对独立的,在编译(compile)时不需要与其他文件互通,只需要在编译成目标文件后在与其他的目标文件做一次链接(link)就行。比如,在文件a.cpp中定义一个全局函数“void
a(){}”,而在文件b.cpp中需要调用这个函数。即使这样,文件a.cpp和文件b.cpp并不需要互相知道对方的存在,而是可以分别的对他们进行编译,编译成目标文件之后再链接,整个程序就可以运行了。
关于头文件和源文件,这里有两个名词,
声明:一般指头文件中的一些变量、方法、类的声明,即变量不赋值,函数不写方法体。
定义(实现):一般在说源文件中经常会出现这个词,就是对引入的头文件中的变量、方法、类等进行初始化,即给他们赋值,写上方法体。
源文件中引入头文件后,可以不用全部定义(实现)头文件中的所有成员(变量、函数、类),用到什么用什么就可以。
在写头文件时需要注意,有固定的样式,即如下方式
… … // 声明、定义语句(你的代码写在这里)
Complex.h,里面声明了一个类,类中声明了一些变量和方法
#pragma once是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次。#pragma once是相关的,有的编译器支持,有的编译器不支持,具体情况可以查看编译器API文档,不过现在大部分编译器都有这个杂注了。
#ifndef,#define,#endif是C/C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。
这里笔者没有将Complex.h中类的所有函数都实现,然后有个比较有意思的事情,去Complex.h文件中看下
有些函数有些绿色波浪线,鼠标靠上去后显示,这个函数没有定义,就是我们没有在引用它的源文件中实现它。
我们点击最下面的显示可能的修补程序,然后点击第一个创建“函数名”的定义(在Complex.cpp中),这时候,编译器就帮我们在引用该头文件的源文件(本文中指Complex.cpp)中将其实现了,然后就没有绿色波浪线了。
源文件中实现引用的头文件中类大体就是这样的,对于函数:返回类型 类名::函数名
5.1、使用没有被源文件实现的函数
如果,我们在main函数中使用complex类,然后Complex.cpp源文件中有个函数并没有被实现,这就会导致错误,比如,笔者最开始并没有在Complex.cpp中实现show()函数,然后直接就在main函数中,如上图,F5一运行就报下面的错误
在Complex.cpp文件中实现show()方法后再运行,就没啥事了。
5.2 源文件中包含了头文件,就一定要将头文件中声明的函数实现吗?
并不需要,笔者并没有在Complex.cpp实现所有Complex.h中complex类的所有函数,一样可以正常运行。
5.3 我们看到,complex类是写在Complex.h中,这很容易导致误解,以为这个头文件名和这个类名要一样,其实不是,比如写一个util.h头文件,里面可以包含word类,excel类,ppt类等。