如果诸葛亮是程序员,如何用程序写出师表。。
作者: 人人网 来源:blog.renren.com/share/308645063/17257436317 代码如下: 运行结果: 作为一名开发者,它把我惹毛了!! 高级程序员必知的 7 种软件架构模式! 本文分享自微信公众号 - 架构师修行之路(jiagoushixiuxing)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
在之前我们详细介绍了 C 语言中如何使用宏定义(#ifndef / #define / #endif)来有效避免头文件被重复 #include,此方式在 C++ 多文件编程中也很常用。
举个例子,如下是一个 C++ 项目,其内部含有 school.h 和 student.h 这 2 个头文件以及 main.cpp 源文件,其各自包含的代码为:
//student.h class Student { //...... }; //school.h #include "student.h" class School { //...... private: Student stu[50]; }; //main.cpp #include "student.h" #include "school.h" int main() { //...... return 0; }
运行此项目会发现,编译器报“Student 类型重定义”错误。这是因为在 school.h 文件中已经 #include 了一次 "student.h",而在 main.cpp 主程序又同时 #include 了 "school.h" 和 "student.h",即 Student 类的定义被引入了 2 次,C++不允许同一个类被重复定义。
有小伙伴可能想到,既然 School.h 文件中已经引入了 Student 类,那去掉 main.cpp 主程序引入的 student.h 文件不就可以了吗?这样确实可以避免重复引入 Student 类,但此方式并不适用于所有“重复引入”的场景。
C++ 多文件编程中,处理“多次 #include 导致重复引入”问题的方式有以下 3 种。
————————
在实际多文件开发中,我们往往使用如下的宏定义来避免发生重复引入:
#ifndef _NAME_H
#define _NAME_H
//头文件内容
#endif
其中,_NAME_H 是宏的名称。需要注意的是,这里设置的宏名必须是独一无二的,不要和项目中其他宏的名称相同。
当程序中第一次 #include 该文件时,由于 _NAME_H 尚未定义,所以会定义 _NAME_H 并执行“头文件内容”部分的代码;当发生多次 #include 时,因为前面已经定义了 _NAME_H,所以不会再重复执行“头文件内容”部分的代码。
也就是说,我们可以将前面项目中的 student.h 文件做如下修改:
#ifndef _STUDENT_H #define _STUDENT_H class Student { //...... }; #endif
虽然该项目 main.cpp 文件中仍 #include 了 2 次 "student.h",但鉴于 _STUDENT_H 宏只能定义一次,所以 Student 类也仅会定义一次。再次执行该项目会发现,其可以正常执行。
除了前面第一种最常用的方式之外,还可以使用 #pragma one 指令,将其附加到指定文件的最开头位置,则该文件就只会被 #include 一次。
我们知道,#ifndef 是通过定义独一无二的宏来避免重复引入的,这意味着每次引入头文件都要进行识别,所以效率不高。但考虑到 C 和 C++ 都支持宏定义,所以项目中使用 #ifndef 规避可能出现的“头文件重复引入”问题,不会影响项目的可移植性。
和 ifndef 相比,#pragma once 不涉及宏定义,当编译器遇到它时就会立刻知道当前文件只引入一次,所以效率很高。
但值得一提的是,并不是每个版本的编译器都能识别 #pragma once 指令,一些较老版本的编译器就不支持该指令(执行时会发出警告,但编译会继续进行),即 #pragma once 指令的兼容性不是很好。
目前,几乎所有常见的编译器都支持 #pragma once 指令,甚至于 Visual Studio 2017 新建头文件时就会自带该指令。可以这么说,在 C/C++ 中,#pragma once 是一个非标准但却逐渐被很多编译器支持的指令。
除此之外,#pragma once 只能作用于某个具体的文件,而无法向 #ifndef 那样仅作用于指定的一段代码。
这里仍以前面的 "student.h" 文件为例,将其内容修改为:
#pragma once class Student { //...... };
再次运行项目,同样可以正常执行。
C99 标准中新增加了一个和 #pragma 指令类似的 _Pragma 操作符,其可以看做是 #pragma 的增强版,不仅可以实现 #pragma 所有的功能,更重要的是,_Pragma 还能和宏搭配使用。
有关 _Pragma 操作符更多的功能和用法,本节不做详细讲解,这里仅介绍如何用 _Pragma 操作符避免头文件重复引入。
当处理头文件重复引入问题时,可以将如下语句添加到相应文件的开头:
_Pragma("once")
比如,将该语句添加到前面项目中 student.h 文件中的开头位置,再次执行项目,其可以正常执行。
事实上,无论是 C 语言还是 C++,为防止用户重复引入系统库文件,几乎所有库文件中都采用了以上 3 种结构中的一种,这也是为什么重复引入系统库文件编译器也不会报错的原因。
本节介绍了 3 种避免头文件被重复引入的方法,其中 #pragma once 和 _Pragma("once") 可算作一类,其特点是编译效率高,但可移植性差(编译器不支持,会发出警告,但不会中断程序的执行);而 #ifndef 的特点是可移植性高,编译效率差。读者可根据实际情况,挑选最符合实际需要的解决方案。
除非对项目的编译效率有严格的要求,强烈推荐读者选用第一种解决方案,即采用 #ifndef / #define / #endif 组合解决头文件被重复引入。
另外在某些场景中,考虑到编译效率和可移植性,#pragma once 和 #ifndef 经常被结合使用来避免头文件被重复引入。比如说:
#pragma once #ifndef _STUDENT_H #define _STUDENT_H class Student { //...... }; #endif
当编译器可以识别 #pragma once 时,则整个文件仅被编译一次;反之,即便编译器不识别 #pragma once 指令,此时仍有 #ifndef 在发挥作用。
微信关注我们
转载内容版权归作者及来源网站所有!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。
Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。
Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。
Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。