c++头文件的简单使用

c++的文件分为两个部分,头文件.h和执行文件.cpp,一个c++文件可以由多个头文件和执行文件组成,头文件不会被编译,但它的内容会被编译,当.cpp文件编译时,包含的头文件内容会被合到相应的.cpp文件中进行编译,c++支持分别编译,一个.cpp文件中可以使用另一个.cpp的函数,但是它们之间的编译可以是独立的,此时只需要在使用的那个.cpp文件中声明需要的那个函数就行,声明与定义是不同的两个概念,声明只需要写出函数的形式,表明有这么个东西就行,定义需要完整地描述函数的实现过程,如果需要声明的东西太多,我们就可以将它们都放在头文件里,这样,只需要在.cpp里#include "头文件名"就可以使用包含的函数了,下面是一个简单的例子,实现的平台是linux ubuntu 14.04:

建立三个文档:main.cpp、print.cpp、header.h,具体内容如下:

-------------main.cpp---------------

#include "header.h"
int main()
{
char ch = 'a';
print(ch);
}

------------print.cpp----------------

#include<iostream>
using namespace std;
void print(char ch)
{
//a ++;
cout << ch << endl;
}

---------header.h-------------

void print(char);

在linux下进入文件所在目录,然后用“g++ main.cpp -c”和“g++ print.cpp -c”编译.cpp文件,编译完成后会生成print.o和main.o两个目标文件,用“g++ print.o main.o -o ch”进行链接,最后用“./ch”运行文件,结果如下:


头文件中不能出现定义的语句,因为声明可以进行多次,但是定义如果进行多次就会出现重定义的问题,试想如果只是在一个.cpp文件包含头文件还好,如果同时有多个.cpp文件包含同一个头文件的话,那么编译器便不知道应该听从那个定义了,如下所示,我们在头文件header.h中定义一个变量a,在main.cpp和print.cpp中同时包含该头文件,结果在链接的时候便会提示重定义问题:


头文件中只能包含变量或者函数的声明,如:“extern int a;“和“void f();”,但有三种情况除外,const对象的定义、inline内联函数的定义、类的定义。

1) const对象默认非extern,只在被包含文件中可见,在其他文件不可见,不会导致重定义,且const值不可更改,所有文件看到的值相同,同理stacic对象也可以定义;

2) 内联函数不会单独进行编译,编译器会在遇到时进行内联展开,所以编译器需要看到内联函数的完整定义,c++规定,内联函数可以进行多次定义,但是在一个.cpp文件中只能出现一次,且在所有.cpp文件中定义相同,所以内联函数可以在头文件中定义。

3) 编译器需要在类完全可见的情况下才能对类的对象进行布局,如,类的内存布局,一般情况下,把类的定义放在头文件中,而把函数成员的实现代码放在一个.cpp文件中。

上述例外可以在不同的源文件多次定义,但是不能在同一个源文件中多次定义,为了确保同一.cpp文件不会包含多次头文件的定义,可以在头文件中使用

#ifndef *** //名字任意取,不重复就好,一般用对应头文件名的全大写来表示,如,HEADER_H

#define ***

...

#endif

来保证头文件不会被重复定义,下面是一个实际的例子,header.h里面已经包含了temp.h,main.cpp同时包含了header.h和temp.h,不使用#ifndef的结构,temp.h会被重复包含,其中的内容就会重定义,使用#ifndef结构,在编译前会先检查temp.h是否已经定义,若定义过则不再定义,可很好地防止重定义的情况。

-------------main.cpp---------------

#include "header.h"
#include "temp.h"
int main()
{
char ch = 'a';
print(ch);
}

------------print.cpp----------------

#include<iostream>
using namespace std;
void print(char ch)
{
cout << ch << endl;
}

---------header.h-------------

#ifndef   _bbb_   
#define   _bbb_ 
#include "temp.h"
void print(char);
class b{};
#endif

---------temp.h--------------

#ifndef   _aaa_   
#define   _aaa_   
class aaa{};  
#endif

--------------------------------


参考文献:http://www.cnblogs.com/lidabo/archive/2012/04/17/2454568.html

### 使用万能头文件与预编译头文件的最佳实践 #### 预编译头文件的作用 预编译头文件是提升 C++ 编译速度的重要手段之一。这类文件允许将频繁使用的标准库或其他第三方库预先处理并保存起来,在后续编译过程中可以直接加载这些已处理的结果,从而节省大量时间[^1]。 #### 创建预编译头文件的方法 对于大多数现代 IDE 和构建系统而言,设置预编译头非常简单。通常只需要指定一个特殊的源文件作为入口点,并在此处包含所有想要提前编译的头文件即可。例如: ```cpp // precompiled_headers.h #ifndef PRECOMPILED_HEADERS_H_ #define PRECOMPILED_HEADERS_H_ #include <iostream> #include <string> #include <vector> #endif // !PRECOMPILED_HEADERS_H_ ``` 接着可以在项目的其他部分通过如下方式引入该预编译单元: ```cpp #include "precompiled_headers.h" ``` 需要注意的是,不是所有的头文件都适合放入预编译头中;应优先考虑那些稳定不变且被广泛使用的组件,比如 STL 容器类或 I/O 流等[^2]。 #### 关于所谓的“万能头文件” 所谓“万能头文件”,实际上是指一种试图一次性包含尽可能多的标准库和其他常用资源的做法。然而这种做法并不推荐,因为它可能导致不必要的依赖关系以及潜在性能损失。更好的策略是在必要时单独添加所需的特定模块而不是盲目追求全面覆盖[^3]。 总之,虽然存在所谓的“万能头文件”的概念,但在实际应用中更提倡有针对性地选用合适的预编译技术来优化项目结构和编译效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

句号(在IT行业摸爬滚打)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值