Learn C++学习笔记:第二章-函数

本文介绍了C++预处理器的基本概念,包括宏定义、条件编译指令的使用,以及头文件的管理技巧。详细解释了如何通过标头保护避免重复定义的问题,提供了有效的头文件包含策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本学习笔记来源于免费教程 Learn C++

2.10 预处理器简介

2.10.1宏定义

基本语法:

#define identifier substitution_text

当预处理器遇到此指令时,标识符的任何进一步出现都将替换为substitution_text。标识符传统上以全部大写字母键入,使用下划线表示空格。如果substitution_text为空,则标识符被替换为空格。
例子:

#include <iostream>
#define MY_NAME "Alex"
int main()
{
    std::cout << "My name is: " << MY_NAME;
    return 0;
}

但教程并不推荐使用该语法

2.10.2 条件编译

条件编译预处理指令允许你在给定条件下的代码会不会被编译,功能类似if 判断条件:注释 or 执行。有很多不同的条件编译指令,但我们只会覆盖最常用的三个:#ifdef,#ifnf 和 #endif
如果被定义到函数内,则类似于局部变量,作用范围只限于函数。

#include <iostream>
#define PRINT_JOE
int main()
{
#ifdef PRINT_JOE          // if PRINT_JOE is defined
    std::cout << "Joe\n"; // execute this code
#endif
    return 0;
}

#ifndef是相反的#ifdef,因为它可以让你检查的标识符是不是没有被定义。
还有 #if 0#endif搭配使用

#if 0                      // Don't compile anything starting here
    std::cout << "Bob\n";
    std::cout << "Steve\n";
#endif                     // until this point

2.11 头文件

当声明越来越多时,就很不方便,可以把这些声明都放到一个文件,称为头文件,这样以后只需要include头文件就行了。
使用有角度的括号来告诉预处理器我们包含了编译器附带的头文件,因此它应该在系统目录中查找该头文件,如:#include <iostream>。双引号告诉预处理器这是我们提供的用户定义的头文件,因此它应首先在当前目录中查找包含源代码的头文件。如果它没有找到头文件,它将检查您在编译器IDE设置中指定的任何其他包含路径。失败了,它将回退到检查系统目录。如:#include "your_header_files.h"

当包含标准库中的头文件时,如果存在,则使用无扩展版本(不带.h)。用户定义的标头仍应使用.h扩展名。

如何包含其他目录的头文件

方法①:包含相对路径

但是如果变更目录,该方法会需要改动比较麻烦

#include "headers/myHeader.h"
#include "../moreHeaders/myOtherHeader.h"

方法②:编译器里面设置头文件目录

这样当它在当前目录中找不到它们时会看到它们。这通常可以通过在IDE项目设置中设置包含路径或搜索目录来完成。

VS里面:选中项目,右键—属性—VC++目录—包含目录

这种方法是全局影响,对以后所有的项目都有用
如果只是想对当前项目添加头文件:
VS里面:选中项目,右键—属性—C/C++—常规—附加包含目录
在这里插入图片描述

2.12 标头保护(header guards)

假如头文件里面有重复的声明,这样主程序导入之后,就会报重复定义的错误。所以可以通过标头保护避免问题,思路就是加上条件编译指令,如下:

#ifndef SOME_UNIQUE_NAME_HERE
#define SOME_UNIQUE_NAME_HERE
 
// your declarations (and certain types of definitions) here
 
#endif

其中 SOME_UNIQUE_NAME_HERE 按照约定是头文件的全部名字,并且全部大写,比如,luck.h,写成LUCK_H。
为了避免重复,推荐 一些好的建议是<PROJECT> _ <PATH> _ <FILE> _H,<FILE> _ <大随机数> _H 或 <文件> _ <创建日期> _H的命名约定

例子如下:
square.h

#ifndef SQUARE_H
#define SQUARE_H
int getSquareSides()
{
    return 4;
}
#endif

geometry.h:

#ifndef GEOMETRY_H
#define GEOMETRY_H
 
#include "square.h"
 
#endif

main.cpp中:

#include "square.h"
#include "geometry.h"
 
int main()
{
    return 0;
}

在预处理器解析所有包含之后,此main()程序如下所示:

#ifndef SQUARE_H // square.h included from main.cpp,
#define SQUARE_H // SQUARE_H gets defined here
 
// and all this content gets included
int getSquareSides()
{
    return 4;
}
 
#endif // SQUARE_H
 
#ifndef GEOMETRY_H // geometry.h included from main.cpp
#define GEOMETRY_H
#ifndef SQUARE_H // square.h included from geometry.h, SQUARE_H is already defined from above
#define SQUARE_H // so none of this content gets included
 
int getSquareSides()
{
    return 4;
}
 
#endif // SQUARE_H
#endif // GEOMETRY_H
 
int main()
{
    return 0;
}

头文件里面最好不要有定义,因为如果头文件被main()文件和其他的cpp文件包含,那么在main()里面,标头保护不会识别出其他文件里面已经被定义过了,这样就会出现重复定义。所以头文件里面只放声明,不要放定义。

还有一种头部保护的写法。但这不是标准c++的语言,可能有的不支持。

#pragma once

#pragma once

// your code here
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值