zoukankan      html  css  js  c++  java
  • PIMPL(二)

    文档下载

    上一篇文档,PIMPL(一)

    1 如何使用PIMPL

      有多种方式实现PIMPL,这里按照《Effective C++》中介绍的方式。

      1.1 基本步骤

      假设原有Person如下:

    Person.h

    struct Person
    {
     public:
      Person(const int _age);
      void print();
    
     private:
      int age;
    };

     Person.cc

    Person::Person(const int _age)
        : age(_age)
    {}
    
    void
    Person::print()
    {
      std::cout << "Person::print::age=" << age << std::endl;
    }

        1.1.1 将Person改名为PersonImpl

    PersonImpl.h

    struct PersonImpl
    {
     public:
      PersonImpl(const int _age);
      void print();
    
     private:
      int age;
    };

     PersonImpl.cc

    PersonImpl::PersonImpl(const int _age)
        : age(_age)
    {}
    
    void
    PersonImpl::print()
    {
      std::cout << "PersonImpl::print::age=" << age << std::endl;
    }

        1.1.2 抽象public和protected方法

      将PersonImpl中的public和protected方法成Person。Person中的方法实际调用的是PersonImpl中对应的方法,Person的定义中需要使用PersonImpl,在Person.h文件中绝对不能#include “PersonImpl.h”,这样就是做无用功了。

    • 为什么不能将PersonImpl的对象作为Person的成员变量?

      因为Person类的定义中需要知道该类的大小,如果直接使用PersonImpl的对象,那么就必须知道PersonImpl的定义,而我们恰恰希望在Person的定义中隐藏PersonImpl的定义。这时候,指针就大显神通了。因为指针的大小只与操作系统的位数有关(32位的机器都占4个字节,64位的机器都占8个字节),所以我们可以使用指针指向PersonImpl,从而只需要前置声明就可以了。这就是暗度陈仓吧。

    Person.h

    struct PersonImpl;  // 前置声明,PIMPL的关键
    
    struct Person
    {
     public:
      Person(const int _age);
      void print();
    
     private:
      std::shared_ptr<PersonImpl> pImpl;  // 指针,暗度陈仓
    };

     Person.cc

    Person::Person(const int _age)
        : pImpl(new PersonImpl(_age))
    {}
    
    void
    Person::print()
    {
      pImpl->print();
    }

        1.1.3 使用Person

      在其它地方我们就可以使用Person了,例如:

    int main()
    {
      Person p(1);
      p.print();
      
      return 0;
    }

        1.1.4     示例源码下载

    2 优缺点

      2.1 优点

    • 改变类的私有成员无需重新编译依赖它的文件,所以整个工程重新编译的速度会快很多。
    • 头文件中采用声明式,因此编译时间会快很多。
    • 接口与实现的分离,更有利于单元测试。

      2.2 缺点

    • 实现者需要做更多的工作。
    • 代码会变得不易理解。
    • 运行时动态的获取要执行的方法,性能降低。
    • 需要注意定义拷贝构造换函数或将其禁用。

    3 总结

      如《Effective C++》中所说:

    •   如果使用object reference或object pointers可以完成任务,就不要使用objects
    •   尽量以class声明式替换class定义式

    4 参考

    1. 《effective C++》 条款31:将文件间的编译关系降至最低
    2. PIMPL Idiom: http://c2.com/cgi/wiki?PimplIdiom
  • 相关阅读:
    函数
    函数知识点 --- 函数的认知,组成,格式 --------------- #10
    打包app
    vue ie
    css position
    awesome vue
    20110636乐建18588529432
    vue2.0-基于elementui换肤[自定义主题]
    三目运算符,多条件判断
    微信二次开发准备工作
  • 原文地址:https://www.cnblogs.com/lovers/p/pimpl2.html
Copyright © 2011-2022 走看看