首页 > 代码库 > PIMPL(二)
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
struct PersonImpl; // 前置声明,PIMPL的关键 struct Person { public: Person(const int _age); void print(); private: std::shared_ptr<PersonImpl> pImpl; // 指针,暗度陈仓 };
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 参考
- 《effective C++》 条款31:将文件间的编译关系降至最低
- PIMPL Idiom: http://c2.com/cgi/wiki?PimplIdiom
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。