zoukankan      html  css  js  c++  java
  • PIMPL惯用法

    PIMPL是“Pointer to IMPLementation”的缩写,它是一种编译防火墙——一种防止修改一个头文件会触发许多源文件被重编译的机制———的编程惯用法。
    下面举一个例子,假设有一个类BigClass,它有一些内联函数,且和一些其他的类有使用关系(Foo类、Bar类、Baz类等),代码如下:

    //bigclass.h
    #include "foo.h"
    #include "bar.h"
    #include "baz.h"
    
    class BigClass{
    public:
    	BigClass();
    	void f1(int a) {...}
    	void f2(float f) {...}
    	Foo foo;
    	Bar bar;
    	Baz baz;
    };
    

    这样写是有一个问题的,那就是一旦bigclass.h、foo.h、bar.h或是baz.h的任何地方发生了改动,都会导致引用bigclass.h的文件被重编译,如果工程比较大,BigClass被很多文件引用的话,就会导致编译时间边长。
    为了解决这个问题,我们可以使用一个过渡类Impl来当一个中间商的角色:

    //bigclass.h
    class Impl;
    class BigClass{
    public:
    	Bigclass();
    	void f1(int a);
    	char f2(float f);
    	Impl * impl;
    }
    

    C++允许声明一个指向未完成类型的指针,在上面的代码中,Impl就是一个未完成类型。它的实现放在cpp文件中:

    //bigclass.cpp
    #include "foo.h"
    #include "bar.h"
    #include "baz.h"
    #include "bigclass.h"
    
    class Impl{
    	void g1(int a);
    	char g2(float f);
    	Foo foo;
    	Bar bar;
    	Baz baz;
    };
    
    void Impl::g1(int a)
    {
    	...
    }
    
    char Impl::g2(float f)
    {
    	...
    }
    
    Bigclass::Bigclass()
    {
    	impl = new Impl;
    }
    
    void BigClass::f1(int a)
    {
    	impl->g1(a);
    }
    

    通过这样实现,在编译时,针对foo.h、bar.h、baz.h或是对Impl的改动都会重新编译bigclass.cpp,但是bigclass.h不会改变,这就限制了重编译的范围。这样引用bigclass.h的文件也不会再重新编译,减少了编译的时间。
    这种方法的缺点是会给程序带来延迟,因为在BigClass的声明与实现之间增加了Impl作为中间层,会增加成员函数调用;再加上现在编译器的编译时间已经比之前大大缩短,因此如果不是一个非常大的类,被非常多的文件引用的话,其实现在也没有必要使用该方法。

  • 相关阅读:
    freebsd安装mysql
    freebsd安装ports
    分布式拒绝服务攻击
    如何用命令获知当前是一年中的第多少周和今天是周几
    freebsd软件包下载地址
    mod_wsgi的两种模式
    freebsd中/etc/rc.conf配置文件导致不能启动的问题
    进程ID[PID(Process ID)]与端口号[(Port ID)]的联系
    Java EE之HttpServletRequest
    Chrome之控制台使用【转载】
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/13729098.html
Copyright © 2011-2022 走看看