• 语言基础(4):文件编译原理


    1、头文件和源文件应该写什么

    头文件和源文件写什么,原则取决于C++编译机制,C++语言以"xxx.cpp"为单位进行编译生成 xxx.obj, 然后目标文件链接生成 xxx.exe (windows),类似 xxx.h 文件是不参与编译,头文件主要通过 #include 宏,将头内容复制到源文件。所以如果在头文件定义了一个变量或这函数并且头文件被重用(多处包含),此时编译就会报出“重定义”!

    因此,C++头文件应该写的内容是变量和函数的声明,注意是声明!!!而不能是定义(例外见下一节)。源文件中写变量和函数的定义,当然也可以在源文件中同时写声明和定义(此时变量或函数为该源文件私有,在其他文件使用时,需要使用extern声明)。

    举个栗子

    // test.h
    #ifndef _TEST_H_
    #define _TEST_H_
     
    #include<string>
    
    using namespace std;
    
    string str;
    extern void show();
     
    #endif
    
    // test.cpp
    #include "test.h"
    #include<iostream>
    #include<string>
     
    str = "Hi, I'm test!"
    void show()
    {
        cout<< str << endl;
    }
    
    

    #2、头文件例外情况 ##2.1 static变量  static变量具有内链接属性,所以对外不文件不可见,不会产生命名冲突。值得一提 const 变量有时也在头文件中定义,这是因为 const 变量也是内链接的,但如果是用 extern const组合修饰,则变量不再是内链接的。此外,修饰组合 static const 常用来修饰文件内的常量。

    2.2 inline函数

    inline函数默认也是内链接属性的,所以不会产生函数重定义,当然使用extern inline组合修饰,就不能放在头文件了。

    2.3 类定义

    为什么头文件可以定义类,而不会产生重命名,因为类定义具有内链接属性,这和变量声明、函数声明并无区别,除此之外 它属于类型定,如果说其他文件里重复定义类,分别取包含别亦,亦不会产生冲突(所以命名空间很重要啊)。

    根本来讲,之所以存在链接属性、以及上面三种例外,遵顼基本的原则: "在头文件中定义这些实体,是因为编译器需要它们的定义(不只是声明)来产生代码"。

    PS:我们知道源文件编译会生成符号表,其实包含了两张表:
    未解决符号表

    提供了在该编译单元引用,但是定义不在本编译单元的符号的地址(拥有者是编译单元)

    导出符号表

    提供了本编译单元具有定义,而且可以提供给其他编译单元使用的符号和地址(拥有者是编译单元)。

    而所谓内链接属性就是不在导出符号表中的变量、函数或者类对应的符号,相对应的就是外链接属性,不再赘述。

    对应存在一个“单一定义规则”(One-Definition Rule, ODR)。根据此规则, 如果对同一个类的两个定义完全相同且出现在不同编译单位,会被当作同一个定义,其实这个规则是个表象的陈述,原理如上所揭示。


    3、避免符号重定义的办法

    • 使宏变量标识(c++的语法)
    #ifndf _XXX_H_
    #define _XXX_H_
     
    //content
     
    #endif
    
    

    缺点:本方法可能会产生宏名称"撞车",从而产生漏包含一些头文件中定义的内容,最终产生缺少定义错误!

    • 使用 #program once(编译器支持)

    缺点:本方法是针对文件物理上的只编译一次,如果两个不同名的文件,保存了相同内容并且均包含在项目中,则会出现重定义错误。不过比起 1,这个错误更易排查,所以使用更广,但是这个宏只属于VC编译器,不在标准定义范围。

  • 相关阅读:
    【Services】【Web】【tomcat】配置tomcat支持https传输
    【Services】【Web】【apr】安装apr
    【Services】【Web】【Nginx】静态下载页面的安装与配置
    【Linux】【Problems】在fedora 9上解决依赖问题
    【Java】【设计模式】单例设计模式
    【Linux】【Shell】【text】awk
    【Linux】【Shell】【Basic】字符串操作
    【Linux】【Shell】【Basic】数组
    Linux上常用插件的一些命令(十)
    常见HTTP状态码
  • 原文地址:https://www.cnblogs.com/wnwin/p/10700189.html
Copyright © 2020-2023  润新知