C++ .h&.hpp&.cpp

表格概括

文件类型作用内容优点缺点应用场景
.h (头文件)声明函数、变量、类和其他类型的接口函数声明、宏定义、类型定义和常量定义提高代码重用性、便于其他文件调用函数和变量不包含实现代码、可能导致编译问题声明函数和变量、定义宏和常量、提供类型定义
.cpp (源代码文件)实现函数、类和其他类型的实现函数实现代码、变量初始化和其他逻辑代码包含实现代码、可以独立编译不适合声明函数和变量、可能导致编译问题实现函数和类、初始化变量、编写逻辑代码
.hpp (头文件)声明模板函数和类模板函数和类声明、类型定义可以声明模板函数和类、便于其他文件调用模板函数和类不包含实现代码、可能导致编译问题声明模板函数和类、提供类型定义

.hpp

本质

hpp是Header Plus Plus 的简写,实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布lib与dll,因此非常适合用来编写公用的开源库。

注意点

  1. 不可包含全局对象和全局函数
    由于hpp本质上是作为.h被调用者include,所以当hpp文件中存在全局对象或者全局函数,而该hpp被多个调用者include时,将在链接时导致符号重定义错误。要避免这种情况,需要去除全局对象,将全局函数封装为类的静态方法。
  2. 类之间不可循环调用

    在.h和.cpp的场景中,当两个类或者多个类之间有循环调用关系时,只要预先在头文件做被调用类的声明即可,如下:

  3.     class B;
     
        class A{
     
        public:
     
             void method(B b);
     
        };
     
        class B{
     
        public:
     
             void method(A a);
     
        };
    

    在hpp场景中,由于定义与实现都已经存在于一个文件,调用者必需明确知道被调用者的所有定义,而不能等到cpp中去编译。因此hpp中必须整理类之间调 用关系,不可产生循环调用。同理,对于当两个类A和B分别定义在各自的hpp文件中,形如以下的循环调用也将导致编译错误:

  4.     //a.hpp
     
        #include "b.hpp"
     
        class A{
     
        public:
     
            void someMethod(B b);
     
        };
     
        //b.hpp
     
        #include "a.hpp"
     
        class B{
     
        public:
     
            void someMethod(A a);
     
        };
    

    3.不可使用静态成员

  5. 如果类含有静态成员,则在hpp中必需加入静态成员初始化代码,当该hpp被多个文档include时,将产生符号重定义错误。唯一的例外是const static整型成员,因为在vs2003中,该类型允许在定义时初始化,如:

  • class A{
    
         public:
    
           const static int intValue = 123;
    
         };
    

    有静态成员场景解决方法

类中仅有一个静态成员时,且仅有一个调用者时,可以通过局域静态变量模拟

    //方法模拟获取静态成员
    someType getMember()
 
    {
 
       static someType value(xxx);//作用域内静态变量
 
       return value;
 
    }

类中有多个方法需要调用静态成员,而且可能存在多个静态成员时,可以将每个静态成员封装一个模拟方法,供其他方法调用。

    someType getMemberA()
 
    {
 
       static someType value(xxx);//作用域内静态变量
 
       return value;
 
    }
 
    someType getMemberB()
 
    {
 
       static someType value(xxx);//作用域内静态变量
 
       return value;
 
    }
 
   void accessMemberA()
 
    {
 
       someType member = getMemberA();//获取静态成员
 
     };
 
    //获取两个静态成员
 
    void accessStaticMember()
 
    {
 
       someType a = getMemberA();//获取静态成员
 
       someType b = getMemberB();
 
     };

第二种方法对于大部分情况是通用的,但是当所需的静态成员过多时,编写封装方法的工作量将非常巨大,在此种情况下,建议使用Singleton模式,将被调用类定义成普通类,然后使用Singleton将其变为全局唯一的对象进行调用。

兼容性

  1. ​​​​​​​在混合使用C和C++的项目中,使用.h和.hpp后缀可能有助于区分C头文件和C++头文件。这有助于避免在不支持C++特性的C代码中错误地包含C++头文件。

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

**K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值