这一篇主要讲一下头文件的相关内容
其实如果学了几门语言之后就会发现,头文件是个相当独特的东西,在JAVA,Python中都没有头文件这么个东西。而且头文件不只是个简单的声明,还有很多重要的用途。
如果我们观察这个项目,会发现有很多文件夹,但这并不限制你在哪里建立文件,比如你可以在头文件夹里写.cpp文件,在源文件里写头文件,严格意义上来说他们根本不是文件夹,而是一种过滤器。
一开始我们在Main文件中输入
#include<iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
int main()
{
Log("Hello World!");
}
在Log文件中输入
void InitLog()
{
Log("Initializing Log");
}
编译之后VS报错说在Log.cpp文件中找不到所谓的Log函数,因此我们就需要一个函数声明,告诉编译器我们定义了这个函数,只是它在其他地方,将Log.cpp改成
void Log(const char* message);
void InitLog()
{
Log("Initializing Log");
}
这时在进行编译就可以顺利通过,我们告诉编译器“嘿,这里有个Log函数,返回void,接收一个const char*的变量”。
但是我们还可以有另一种办法,就是应用头文件。
我们在头文件夹中建立头文件(再次声明头文件可以在任何地方建立,只是这样看起来更好)。Main.cpp,Log.cpp,Log.h代码分别为
//Main.cpp
#include<iostream>
#include"Log.h"
int main()
{
InitLog();
Log("Hello World!");
}
//Log.cpp
#include"Log.h"
#include<iostream>
void InitLog()
{
Log("Initializing Log");
}
void Log(const char* message)
{
std::cout << message << std::endl;
}
//Log.h
#pragma once
void Log(const char* message);
void InitLog();
运行之后成功的输出了结果,这样我们就把函数的声明,定义,和调用放在了三个不同的.cpp文件中使用
当我们新建一个头文件时,系统会在开始自动加上一句#pragma once
,很显然这是一个预编译指令,叫做头文件保护符(header guard),以防止我们将单个头文件多次include到同一个.cpp文件中,如果我们回想一下#include
的作用,我们就会理解为什么防止我们这么做。因为我们会在文件中重复复制粘贴同样的内容,这肯定会带来定义冲突的问题。
比如我们可以在头文件中加入struct Player {};
,如果我们重复的include头文件,就会有多个Player被定义,屏蔽掉头文件保护符并且重复include头文件,VS报错Player被定义了两次。
当然头文件保护符还有另外的形式
#ifndef _LOG_H
#define _LOG_H
void InitLog();
void Log(const char* message);
struct Player {};
#endif
在这种情况下,_LOG_H未被定义,那就会执行后续代码的内容,如果已有定义,后面的内容都不会被include。
另外在引用头文件时会有两种格式
#include<iostream>
#include"log.h"
这里引号代表相对路径,甚至可以#include"../"log.h"
来返回上一级文件,而<>则不存在这种问题。