4、c++头文件、源文件使用小记

前言:最近使用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并不需要互相知道对方的存在,而是可以分别的对他们进行编译,编译成目标文件之后再链接,整个程序就可以运行了。

关于头文件和源文件,这里有两个名词,

声明:一般指头文件中的一些变量、方法、类的声明,即变量不赋值,函数不写方法体。

定义(实现):一般在说源文件中经常会出现这个词,就是对引入的头文件中的变量、方法、类等进行初始化,即给他们赋值,写上方法体。

源文件中引入头文件后,可以不用全部定义(实现)头文件中的所有成员(变量、函数、类),用到什么用什么就可以。

三、代码

3.1 目录结构

其中头文件中有三个文件,Complex.h、person.h、Test.h,对用三个名一样的源文件及一个main函数。 

3.2 头文件声明

在写头文件时需要注意,有固定的样式,即如下方式

#ifndef _Complex_H_
#define _Complex_H_

… … // 声明、定义语句(你的代码写在这里)
  
#endif

Complex.h,里面声明了一个类,类中声明了一些变量和方法 

#pragma once
#ifndef _Complex_H_
#define _Complex_H_

class complex {
private:
	double real, imag;
public:
	complex();//空的构造函数
	complex(double,double);//默认参数的构造函数
	void set(double,double);//设置函数
	double getReal();//获取实部函数
	double getImag();//获取虚部函数
	double module();//获取复数模的函数

	//复数加减乘除函数
	complex add(complex);
	complex decrease(complex);
	complex multiply(complex);
	complex divide(complex);
	//复数显示函数
	void show();
};

#endif // !_Complex_H_

说明:大家可能注意到了,我在Complex.h的开头使用了#pragma once,其实#pragma once和

#ifndef _SOMEFILE_H_
#define _SOMEFILE_H_
.......... // 一些声明语句
#endif

差不多。

#pragma once是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次。#pragma once是编译器相关的,有的编译器支持,有的编译器不支持,具体情况可以查看编译器API文档,不过现在大部分编译器都有这个杂注了。

#ifndef,#define,#endif是C/C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式。

3.3 源文件实现

#include<stdio.h>
#include<cmath>
#include"Complex.h"

complex::complex()
{
	real = 0;
	imag = 0;
}

complex::complex(double a, double b) {
	real = a;
	imag = b;
}

void complex::set(double a,double b) {
	real = a;
	imag = b;
}

double complex::getReal() {
	return real;
}

double complex::getImag() {
	return imag;
}

complex complex::add(complex a) {
	double real = this->real + a.getReal();
	double imag = this->imag + a.getImag();
	return complex(real,imag);
}

void complex::show()
{
	if (imag >= 0)
	{
		printf("%.2f+%.2fi", real, imag);
	}
	else
	{
		printf("%.2f%.2fi", real, imag);
	}
	return;
}

这里笔者没有将Complex.h中类的所有函数都实现,然后有个比较有意思的事情,去Complex.h文件中看下

有些函数有些绿色波浪线,鼠标靠上去后显示,这个函数没有定义,就是我们没有在引用它的源文件中实现它。

 

我们点击最下面的显示可能的修补程序,然后点击第一个创建“函数名”的定义(在Complex.cpp中),这时候,编译器就帮我们在引用该头文件的源文件(本文中指Complex.cpp)中将其实现了,然后就没有绿色波浪线了。

 

四、说明

源文件中实现引用的头文件中类大体就是这样的,对于函数:返回类型 类名::函数名 

五、踩坑

5.1、使用没有被源文件实现的函数

main函数中使用 Complex.cpp

#include"Complex.h"
#include<stdio.h>

int main() {
	complex A;//验证默认构造函数
	printf("A为:");
	A.show(); 
	printf("\n");

	complex B(2, -1);//验证两个参数构造函数
	printf("B为:"); 
	B.show(); 
	printf("\n");
}

如果,我们在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类等。

  • 21
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值