为什么有头文件和.cpp文件?

为什么C ++有头文件和.cpp文件?


那么,主要原因是将接口与实现分开。 头文件声明了“什么”类(或正在实现的任何内容)将会执行,而cpp文件定义了它将如何执行这些功能。

这减少了依赖性,以便使用头的代码不一定需要知道实现的所有细节和任何其他只需要的类/头。 这将减少编译时间以及实现中的某些内容所需的重新编译量。

这并不完美,你通常会使用像Pimpl Idiom这样的技术来正确分离界面和实现,但这是一个好的开始。


C ++编译

C ++编译分两个主要阶段完成:

  • 第一种是将“源”文本文件编译为二进制“对象”文件:CPP文件是编译文件,编译时不需要关于其他CPP文件(甚至是库)的任何知识,除非通过原始声明或标题包含。 CPP文件通常被编译成一个.OBJ或一个.O“对象”文件。

  • 其次是将所有“对象”文件连接在一起,从而创建最终的二进制文件(库或可执行文件)。

  • HPP在哪些方面适用于所有这些过程?

    一个贫穷的孤独的CPP文件...

    每个CPP文件的编译独立于所有其他CPP文件,这意味着如果A.CPP需要在B.CPP中定义的符号,如:

    // A.CPP
    void doSomething()
    {
       doSomethingElse(); // Defined in B.CPP
    }
    
    // B.CPP
    void doSomethingElse()
    {
       // Etc.
    }
    

    它不会编译,因为A.CPP无法知道“doSomethingElse”存在......除非A.CPP中有声明,如:

    // A.CPP
    void doSomethingElse() ; // From B.CPP
    
    void doSomething()
    {
       doSomethingElse() ; // Defined in B.CPP
    }
    

    然后,如果您有C.CPP使用相同的符号,则您复制/粘贴声明...

    复制/粘贴警报!

    是的,有一个问题。 复制/粘贴是危险的,难以维护。 这意味着如果我们有一些方法不复制/粘贴,并且仍然声明​​符号,那将是很酷的......我们该怎么做? 通过包含一些文本文件,通常以.h,.hxx,.h ++或者我的首选C ++文件为后缀.hpp:

    // B.HPP (here, we decided to declare every symbol defined in B.CPP)
    void doSomethingElse() ;
    
    // A.CPP
    #include "B.HPP"
    
    void doSomething()
    {
       doSomethingElse() ; // Defined in B.CPP
    }
    
    // B.CPP
    #include "B.HPP"
    
    void doSomethingElse()
    {
       // Etc.
    }
    
    // C.CPP
    #include "B.HPP"
    
    void doSomethingAgain()
    {
       doSomethingElse() ; // Defined in B.CPP
    }
    

    如何include工作?

    实质上,包含文件将会解析并复制粘贴其内容到CPP文件中。

    例如,在下面的代码中,使用A.HPP标题:

    // A.HPP
    void someFunction();
    void someOtherFunction();
    

    ......来源B.CPP:

    // B.CPP
    #include "A.HPP"
    
    void doSomething()
    {
       // Etc.
    }
    

    包含后将成为:

    // B.CPP
    void someFunction();
    void someOtherFunction();
    
    void doSomething()
    {
       // Etc.
    }
    

    一件小事 - 为什么在B.CPP中包含B.HPP?

    在目前的情况下,这是不需要的,B.HPP具有doSomethingElse函数声明,而B.CPP具有doSomethingElse函数定义(它本身就是一个声明)。 但是在更一般的情况下,使用B.HPP进行声明(和内联代码)时,可能没有相应的定义(例如枚举,普通结构等),因此如果B.CPP使用B.HPP的声明。 总而言之,源代码默认包含标题是“很好的品味”。

    结论

    因此头文件是必需的,因为C ++编译器不能单独搜索符号声明,因此必须通过包含这些声明来帮助它。

    最后一句话:你应该为你的HPP文件的内容加上标题守卫,以确保多个包含文件不会破坏任何内容,但总而言之,我相信HPP文件存在的主要原因如上所述。

    #ifndef B_HPP_
    #define B_HPP_
    
    // The declarations in the B.hpp file
    
    #endif // B_HPP_
    

    因为起源于C的概念已经有30年的历史,并且当时它是将多个文件中的代码链接在一起的唯一可行的方法。

    今天,这是一个非常糟糕的破解,它彻底破坏了C ++中的编译时间,导致无数不必要的依赖关系(因为头文件中的类定义暴露了有关实现的太多信息)等等。

    链接地址: http://www.djcxy.com/p/85423.html

    上一篇: Why have header files and .cpp files?

    下一篇: PDB files in VisualStudio bin\debug folders