hpp,顾名思义等于.h加上.cpp,在boost、Xerces等开源库中频繁出现,偶在机缘巧合之下,学得一招半式,遂记录如下,以供参考学习。

    hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布烦人的lib与dll,因此非常适合用来编写公用的开源库。
    hpp的优点不少,但是编写中有以下几点要注意:
   
    1、不可包含全局对象和全局函数。
    由于hpp本质上是作为.h被调用者include,所以当hpp文件中存在全局对象或者全局函数,而该hpp被多个调用者include时,将在链接时导致符号重定义错误。要避免这种情况,需要去除全局对象,将全局函数封装为类的静态方法。
    2、类之间不可循环调用。
    在.h和.cpp的场景中,当两个类或者多个类之间有循环调用关系时,只要预先在头文件做被调用类的声明即可,如下:
    class B;
    class A{
    public:
         void someMethod(B b);
    };
    class B{
    public:
         void someMethod(A a);
    };
    在hpp场景中,由于定义与实现都已经存在于一个文件,调用者必需明确知道被调用者的所有定义,而不能等到cpp中去编译。因此hpp中必须整理类之间调 用关系,不可产生循环调用。同理,对于当两个类A和B分别定义在各自的hpp文件中,形如以下的循环调用也将导致编译错误:
    //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、不可使用静态成员。
    静态成员的使用限制在于如果类含有静态成员,则在hpp中必需加入静态成员初始化代码,当该hpp被多个文档include时,将产生符号重定义错误。唯一的例外是const static整型成员,因为在vs2003中,该类型允许在定义时初始化,如:
    class A{
     public:
       const static int intValue = 123;
     };
    由于静态成员的使用是很常见的场景,无法强制清除,因此可以考虑以下几种方式(以下示例均为同一类中方法)
    1.类中仅有一个静态成员时,且仅有一个调用者时,可以通过局域静态变量模拟
    //方法模拟获取静态成员
    someType getMember()
    {
       static someType value(xxx);//作用域内静态变量
       return value;
    }
    2.类中有多个方法需要调用静态成员,而且可能存在多个静态成员时,可以将每个静态成员封装一个模拟方法,供其他方法调用。
    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();
     };
    3.第二种方法对于大部分情况是通用的,但是当所需的静态成员过多时,编写封装方法的工作量将非常巨大,在此种情况下,建议使用Singleton模式,将被调用类定义成普通类,然后使用Singleton将其变为全局唯一的对象进行调用。
     如原h+cpp下的定义如下:
    class A{
    public:
        type getMember(){
           return member;
        }
        static type member;//静态成员
    }
    采用singleton方式,实现代码可能如下(singleton实现请自行查阅相关文档)
    //实际实现类
    class Aprovider{
    public:
        type getMember(){
           return member;
        }
       type member;//变为普通成员
    }
    //提供给调用者的接口类
    class A{
    public:
        type getMember(){
           return Singleton<AProvider>::getInstance()->getMember();
        }
    }

.h 与 .hpp 文件的更多相关文章

  1. .hpp文件

    hpp在C++中的含义 以前在开源代码里面遇到过,今天看boost源码的时候又遇到了,故学习一下. hPP,计算机术语,用C/C++语言编写的头文件,通常用来定义数据类型,声明变量.函数.结构和类.而 ...

  2. c++中的.hpp文件

    http://blog.chinaunix.net/uid-24118190-id-75239.html hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的 ...

  3. hpp文件简介

    Boost库文件采用的.hpp的后缀,而不是分成两个文件,也就是”.h+.cpp”,之所以这样做是有理由的,首先就是与普通的C/C++头文件区分,另外一个原因就是使Boost库不需要预先编译,直接引用 ...

  4. C++ .h 与 .hpp 的区别

    原文地址:http://blog.csdn.net/f_zyj/article/details/51735416 .hpp,本质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件, ...

  5. .hpp 文件

    .hpp 是 Header Plus Plus 的简写,是 C++程序头文件. 其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp ...

  6. xcode中的.h和.m文件分别是什么意思?各有什么用?

    .h 表示头文件,用来声明各种成员变量,方法,属性之类的.在import的时候用头文件. .m 主要用来实现.h 里声明的方法.举个例子,如果要写一个方法,你要在.h里先声明: - (void)myM ...

  7. Visual Studio 2010中的stdafx.h和targetver.h两个头文件是有什么用?

    来自百度~stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行. Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程 ...

  8. [Objective-c 基础 - 2.5] .h和.m文件,点语法,成员变量作用域

    A. 命令行编译和XCode编译 1.在存在多个.m源码实现文件的情况下,若根据需要引入.m文件,使用命令行仅仅编译主.m文件即可,但是XCode会同时编译全部.m文件,会发生编译错误(重复定义全局变 ...

  9. C语言中.h和.c文件解析(很精彩)

    C语言中.h和.c文件解析(很精彩)   简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程: 1.预处理阶段 2.词法与语法分析 ...

随机推荐

  1. css基础和心得(二)

    css中的某些样式是具有继承性的.它允许样式不仅应用于某个特定html标签元素 而且应用于其后代.如: p{color:red;}  <p>dsffd<spans>sdfasd ...

  2. Web中的无状态含义

    REST架构设计是目前非常火热的概念,已经成为构建web服务时应该遵循的事实标准.REST约束中有一条很重要的规则是“无状态”,但“无状态”是个很抽象的概念,对刚刚接触的人来讲,很难深刻形象的理解.今 ...

  3. C# DataRow[]转换DataTable

    DataTable dt = ... DataRow[] dr = dt.Select("ID=14"); dt = dr.CopyToDataTable();

  4. Openjudge-NOI题库-Pell数列

    题目描述 Description Pell数列a1, a2, a3, ...的定义是这样的,a1 = 1, a2 = 2, ... , an = 2 * an − 1 + an - 2 (n > ...

  5. Flashbuilder 破解方式 4.6 +4.7(网络资源整理)

    Fb4.6 破解方式 安装完成后在安装目录下依次修改下列3个文件: (1).eclipse\plugins\com.adobe.flexbuilder.project_4.6.0.328916\MET ...

  6. AppDelegate 里一个基本的跳转方法,用来在rootView崩溃的时候直接调试我自己的页面

    将 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)lau ...

  7. [译][待续]Chap1.Using neural nets to recognize handwritten digits

    Chapter1 使用神经网络辨识手写数字 人类的视觉系统是自然界的一大奇迹.试看如下的手写数列: 绝大多数人都能毫不费劲地认出这些数字是504192,而这会让人产生识别数字非常简单的错觉.人类大脑的 ...

  8. php 分析

    php  code in D:\10\11\php test in D:\10\11\php\test issue 1: <html><head><title>标记 ...

  9. [转] Android root 原理

    欢迎转载,转载请注明出处:http://www.cnblogs.com/lanrenxinxin/p/5572640.html 0x00 关于root linux和类Unix系统的最初设计都是针对多用 ...

  10. jsvc 以daemon方式运行tomcat

    原理: 使用jsvc来运行服务,没有了默认8005的shutdown端口: 主进程pid为1,fork 2个进程 运行方式参考:http://commons.apache.org/proper/com ...