c++中头文件包含内容以及为何不可重复包含头文件

C++的头文件(通常以.h.hpp为扩展名)一般包含以下内容:

  1. 函数声明:函数的原型,使其他源文件可以调用这些函数。

  2. 类和结构体的声明与定义:包括成员变量和成员函数的声明。

  3. 模板类和模板函数的定义:模板需要在编译时完全可见,所以其实现通常放在头文件中。

  4. 宏定义:使用#define预处理指令定义的宏。

  5. 类型定义:使用typedefusing创建的类型别名。

  6. 枚举类型的定义enum类型的声明。

  7. 内联函数的定义:使用inline关键字的函数,其实现通常放在头文件中。

  8. 外部变量的声明:使用extern关键字声明的全局变量。

  9. 命名空间的声明和使用:定义命名空间以组织代码。

  10. 预处理指令:如包含保护(include guard)#ifndef/#define/#endif#pragma once,防止头文件被重复包含。

头文件的主要作用是声明接口,使多个源文件可以共享代码。在头文件中通常不包含函数的具体实现(模板和内联函数除外),以避免链接时的重复定义错误。

在C++中,函数的重复声明通常不会有问题,编译器允许对同一函数进行多次声明。但是,重复定义函数(即提供函数的实现)是不允许的。

以下是一些在C++中不能重复声明或定义的情况:

  1. 变量定义

    • 全局变量:全局变量只能定义一次。如果在多个地方对同一变量进行了定义(而非声明),链接时会产生“multiple definition”错误。
    • 静态变量:静态变量也只能在同一作用域内定义一次,重复定义会导致编译错误。
  2. 类、结构体和枚举类型的定义

    • 类和结构体:同一作用域内不能重复定义同名的类或结构体。这会导致编译器报类型重定义的错误。
    • 枚举类型:同样,枚举类型也不能在同一作用域内重复定义。
  3. typedefusing类型别名

    • 类型别名:在同一作用域内,不能对同一名称重复定义类型别名。这会引发编译错误。
  4. 函数定义

    • 非内联、非模板函数:函数的实现(定义)只能出现一次。重复定义会在链接阶段产生“multiple definition”错误。
    • 内联函数:内联函数可以在多个翻译单元中定义,但必须保持一致。如果没有inline关键字,重复定义会导致错误。
  5. 宏定义

    • 宏重复定义:如果在未使用#undef的情况下重复定义宏,而且新定义与原定义不同,可能会产生警告或错误。
  6. 模板定义

    • 模板类和模板函数:模板的定义一般放在头文件中,但如果头文件没有包含保护,可能会导致重复定义错误。
  7. 命名空间别名和using声明

    • 命名空间别名:在同一作用域内,不能对同一名称重复创建命名空间别名。
    • using声明:重复的using声明虽然不会导致错误,但可能会引起代码混淆。

为什么需要包含保护(Include Guard)

当一个头文件被多个源文件包含,或者在同一个源文件中被间接多次包含时,如果没有包含保护,以上提到的实体可能会被重复定义或声明,导致编译错误或链接错误。使用包含保护可以确保头文件的内容在同一个翻译单元中只被处理一次,避免重复定义和声明的问题。

示例

假设有一个头文件myheader.h

// myheader.h
struct MyStruct {
    int data;
};

如果在源文件中多次包含myheader.h,而没有包含保护:

#include "myheader.h"
#include "myheader.h" // 重复包含

int main() {
    MyStruct obj;
    return 0;
}

编译时会报错,提示MyStruct重复定义。添加包含保护可以解决这个问题:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

struct MyStruct {
    int data;
};

#endif // MYHEADER_H

总结

  • 重复声明:通常是允许的,如函数和变量的extern声明。
  • 重复定义:在同一作用域或翻译单元中,类型、变量、函数等的重复定义是不允许的。
  • 包含保护:使用#ifndef/#define/#endif#pragma once可以防止头文件内容被重复处理,避免重复定义和声明的问题。

通过理解这些规则,可以编写更健壮的C++代码,避免因重复定义导致的编译和链接错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值