zoukankan      html  css  js  c++  java
  • C++ 头文件:预处理、内联函数、模板函数

    预处理

    • 编译之前(预处理阶段)执行

    • 预处理功能举例

      • #include
      • 头文件保护符
        • 避免同一个文件被include多次
          • 通过判断预处理变量是否已定义:#ifndef、#define、#endif
        • 预处理变量名全局唯一(通常通过头文件中的类名来定义保护符的名字,个人感觉 namespace name + class name 来定义较好)
        • 缺点
          • 如果项目的不同模块中有同名的两个头文件(内容可能不同),其头文件保护符很可能也是相同的,这时可能会造成其中一个头文件被意外exclude
          • #ifndef/#endif需要成对出现
      • #pragma once
        • 同样也是避免同一个文件被include多次
          • 此处“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件
          • 无法对一个头文件中的一段代码作pragma once声明,而只能针对文件
        • 缺点
          • non-standard
          • 如果项目中某个头文件被拷贝多次,编译时会认为这是多个不同头文件(同时也是优点,如项目中不同模块的两个同名但不同内容头文件,不使用头文件保护符,而是使用这种方式就不会意外exclude其中一个)
    • 预处理变量及注意事项

      • #define 指令把一个名字设定为预处理变量
      • #ifdef、#ifndef 检测预处理变量已定义、未定义
      • 预处理变量无视C++语言中关于作用域的规则(即不能提供任何封装性)
      • 整个程序中的 预处理变量(包括头文件保护符)必须唯一

    概念及规则

    • 编译单元:即一个源文件+其include的文件,编译后可生成一个目标文件
    • 可声明多次,但只能定义一次
    • 可重声明函数,但不能重声明结构/类
    • 分离式编译过程中,预处理器在每个编译单元中查找头文件保护符是否被定义

    内联函数

    模板函数

    通常模板函数声明和定义都位于头文件,原因为在同一编译单元内,编译器要根据模板函数定义来实例化模板函数,而实例化模板函数发生的的位置在源文件,因此模板函数的定义应位于头文件

    另外当多个源文件中都有相同的模板函数实例化时,每个编译单元内确实都生成了对应的实例化函数,但它是一个弱符号,最终在链接阶段只会选择其中一个,从而不会出现多重定义问题,具体可参考:链接器如何解析多重定义的全局符号

    重复定义相关测试

    类成员

    • 成员函数定义在头文件中类外部时,可能会有多重定义的错误(编译或者链接阶段都有可能)
    • 成员函数定义在头文件中类内部时为内联函数,不会出现多重定义错误
    • 类静态成员的定义在头文件中类外部时,可能会有多重定义的错误
    • 当不对类静态成员进行定义时,代码中如果有对其访问则会报未定义编译错误

    全局变量

    • 静态全局变量、常量全局变量为内部链接 ,每个编译单元中可保存一份副本,在头文件中的定义不会引起重复定义错误
    • 普通全局变量如果定义在头文件,可能引起重复定义错误

    参考

    《C++ Primer 第五版》
    《Effective C++ 第三版》
    Is #pragma once a safe include guard?
    #ifndef 与 #program once 的区别
    头文件与cpp文件为什么要分开写
    头文件重复包含和变量重复定义
    How is compilation unit defined in c++?
    What is a “translation unit” in C++
    How does the linker handle identical template instantiations across translation units?
    separate-template-class-defn-from-decl

  • 相关阅读:
    javascript Date format(js日期格式化)
    hcharts 教程
    UVA 10594 Data Flow
    UVA 10746 Crime Wave
    UVA 753 A Plug for UNIX
    UVA 11045 My T-shirt suits me
    UVA 10273 Eat or not to Eat?
    UVA 10806 Dijkstra, Dijkstra.
    UVA 10330 Power Transmission
    UVA 10803 Thunder Mountain
  • 原文地址:https://www.cnblogs.com/wangzhiyi/p/12562285.html
Copyright © 2011-2022 走看看