头文件 Header Files传统上用于声明某些函数类型,以便可以用于整个程序中。
例如:在一个文件1中创建函数,然后想在另一个文件2中使用,尝试编译此文件2时,C++不会直到这个文件1的存在,所以需要一个共同的地方来存放声明(并不是定义,因为函数的定义只可以有一次),声明中没有实际的函数定义,没有函数主体,
假定有个函数Log,作用时打印输出,接收一个const char "message",然后cout该信息
//Math.cpp
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
int main()
{
std::cout << "Hello World!" << std::endl;
std::cin.get();
}
//新建Log.cpp
void InitLog()
{
Log("Initialized Log");
//此处Log会报错,这个Log函数并不存在于该文件,该文件不知道Log函数的存在
}
//为了没有error,修改Math.cpp
#include <iostream>
void Log(const char* message)
{
std::cout << message << std::endl;
}
int main()
{
Log("Hello World!");//编译不报错
std::cin.get();
}
//但是Log.cpp仍然报错,Log仍然不存在
//Log.cpp需要什么才会没有错误?告诉Log.cpp文件,Log函数存在,只是定义于别的地方
//使用函数声明!!!
//修改Log.cpp
//直接复制粘贴Log函数的函数签名到Log.cpp文件,尾部用分号结束,例:Log.cpp
void Log(const char* message);//仅仅是函数的声明,无函数主体
void InitLog()
{
Log("Initialized Log");//编译不再报错
}
如果另外创建了别的文件需要使用Log函数:
将Log函数的声明void Log到处复制粘贴?可以但不必要,Header File可以解决该问题。
头文件一般被include到.cpp文件中,将头文件的内容复制粘贴进.cpp文件中,通过#include 预处理语句来实现,#include有从文件复制粘贴到其他文件的能力
创建头文件Log.h
系统自动插入了#pragma once
头文件Log.h中写入函数声明,此时任何想要使用Log函数的地方只需要经过include就可以使用
//Log.h
#pragma once
void Log(const char* message);
void InitLog();
//Log.cpp
#include <iostream> //include后,error消失
#include "Log.h"
void InitLog()
{
Log("Initialized Log");
}
void Log(const char* message)
{
std::cout << message << std::endl;
}
//Main.cpp
#include <iostream>
#include "Log.h"
int main()
{
InitLog();
Log("Hello World!");
std::cin.get();
}
header file中系统自动插入的#pragma once:属于预处理指令,意思是:该文件只include一次
pragma once被称为header guard(头文件保护符),防止把单个头文件多次include到一个单一翻译单元(一个.cpp文件)里,但是不会防止把头文件include到程序的各处。
把单个头文件多次include到一个单一翻译单元(一个.cpp文件)里会得到一个重复的错误。
创建struct示意:
//Log.h
//#pragma once 被注释掉
void Log(const char* message);
void InitLog();
struct Player {};
//Log.cpp文件中,头文件include两次,此时编译会得到'player' struct typr redefinition
#include <iostream>
#include "Log.h"
#include "Log.h"
void InitLog()
{
Log("Initialized Log");
}
void Log(const char* message)
{
std::cout << message << std::endl;
}
程序编写时会include多个头文件,防止声明重复
例,新建Common.h
//Commom.h
#pragma once
# include "Log.h"
//Log.h
//#pragma once
void Log(const char* message);
void InitLog();
struct Player {};
//Log.cpp
#include <iostream>
#include "Log.h"
#include "Common.h"
void InitLog()
{
Log("Initialized Log");
}
void Log(const char* message)
{
std::cout << message << std::endl;
}
依然会报错重定义
原因:将Log include了两次(Log.cpp+Common.h)
将Log.h文件中的#pragma once解除注释
成功编译(解除注释后,察觉到Log.h已被include,不会在二次include)
添加头文件保护符的另外一种方式:(传统方式添加头文件保护符#ifndef)
#ifndef
Log.h
#ifndef _LOG_H
#define _LOG_H
void Log(const char* message);
void InitLog();
struct Player {};
#endif
#ifndef _LOG_H 首先检查_LOG_H这个符号是否存在,如果没有定义,它将把以下代码include到编译里;如果已经被定义了,那么这些都不会被include,会全部被禁用。通过了第一个条件检查后会定义Log.h。下次运行这段代码时,它是已经被定义的状态,所以不会再重复
将文件内容复制到Log.cpp中,注释掉两个原本的.h文件,首次粘贴一切正常,第二次内容变灰,因为Log.h已经被定义了
多数编辑器都支持#pragma once
头文件保护符一起,include语句间会有差异,""或<>
<>是让编译器在所有include路径里搜索文件
""用于include文件存在于该文件的相对位置
例如:有Log.h文件存在于Log.cpp文件的上一级目录,此时可以使用../来返回,返回相对本文件的上一级目录。#include "../Log.h"
对于<>来说,只是说存在于所有include目录的某一个里
其实,""也可以用于编译器include目录的位置
<>只用于编译器的include路径,""用于所有
iostream没有文件扩展名,是个没有扩展名的文件。为了区分C标准库与C++标准库,C标准库的头文件一般都有.h扩展名,而C++没有
10
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)