C++: The PIMPL idiom

什么是PIMPL(pointer to implementation) ? see:

http://stackoverflow.com/questions/8972588/is-the-pimpl-idiom-really-used-in-practice

https://msdn.microsoft.com/en-us/library/hh438477.aspx

http://www.cppsamples.com/common-tasks/pimpl.html

为什么需要PIMPL? Hurb Sutter:

Reason 1:

1. If not used, compilation time would be long as you expected. For example:

1 // headerFile.h
2 class C{
3 //,,,
4 private:
5     AComplicatedType act_;
6 };

The header file containing class C‘s definition must also #include the header containing the definition for  AComplicatedType ,which in turn transitively includes every header that  AComplicatedType might need, and so on. If the headers are extensive, compilation times can be noticably affected.

Reason 2:

That is because C++ performs name lookup and then overload resolution before accessibility checking.

 1 //global function
 2 int Twice(int);               //1
 3
 4 class Calc{
 5 public:
 6     string Twice(string);    //2
 7
 8 private:
 9     char* Twice(char*);     //3
10
11     int Test(){
12         return Twice(21);    //A: error. 2 or 3 would be unviable. Though 1 is viable,
13     }                        // it can‘t be considered because it‘s hidden
14 };
15
16 Calc c;
17 c.Twice("Hello");            //B:error. 3 is inaccessible( 2 would work fine, but it can‘t be
18                              //considered, because 3 is a better choice and  c++ perform overload
19                              //resolution before accessibility checking

As illustrated in the comments above.

Reason 3:

Exeception guarantee.

consider this:

1 class Widget{
2 public:
3     Widget& operator=(const Widget&);
4
5 private:
6     T1 t1_;
7     T2 t2_;
8 };

what happen when  T1 and  T2 is constructing and an exception throwed up ?

This would be a better approach:

 1 class Widget{
 2 public:
 3     Widget& operator=(const Widget&);
 4
 5 private:
 6     struct Impl;
 7     shared_ptr<Impl> pimpl_;
 8 };
 9
10 Widget& Widget::operator=(const Widget&){
11     shared_ptr<Impl> temp( new Impl(/*...*/) );
12
13 // change temp->t1_ to temp->t2_;
14 // if it fail, then throw, else commit using
15
16     pimpl_ = temp;
17     return *this;
18 };
时间: 2024-10-13 22:44:42

C++: The PIMPL idiom的相关文章

pimpl idiom

pimpl idiom flyfish 2014-9-30 pimpl是Pointer to implementation的缩写 为什么要使用pimpl 1最小化编译依赖 2接口与实现分离 3可移植 pimpl idiom也被称作Cheshire Cat , Compiler Firewall idiom.,d-pointer 这个技术在设计模式中作为桥接模式(Bridge pattern.)来描写叙述 看MSDN的演示样例 Pimpl header // my_class.h class my

Pimpl Idiom /handle body idiom

在读<Effective C++>和项目源代码时,看到pImpl Idiom.它可以用来降低文件间的编译依赖关系,通过把一个Class分成两个Class,一个只提供接口,另一个负责实现该接口,实现接口与实现的分离.这个分离的关键在于“以声明的依赖性”替换“定义的依赖性”,而编译依赖性最小化的本质是:让头文件尽可能的自我满足,万一做不到,则让它与其他文件内的声明式(而非定义式)相依. 引用这里的一些描述:The Pimpl idiom, also known as the compilation

PIMPL(一)

1 参考 <effective C++> 条款31:将文件间的编译关系降至最低 PIMPL Idiom: http://c2.com/cgi/wiki?PimplIdiom 2 什么是PIMPL? PIMPL是指pointer to implementation.通过使用指针的方式隐藏对象的实现细节.是实现"将文件间的编译依存关系降至最低"的方法之一.另一个方式是通过接口实现,但其原理一样. PIMPL又称作"编译防火墙"."笑脸猫技术&quo

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 P

《Effective C++》:条款31:将文件间的编译依存关系降至最低

假如你在修改程序,只是修改了某个class的接口的实现,而且修改的是private部分.之后,你编译时,发现好多文件都被重新编译了.这种问题的发生,在于没有把"将接口从实现中分离".Class的定义不只是详细叙述class接口,还包括许多实现细目: class Person{ public: Person(const std::string& name, const Date& birthday, const Address& addr); std::strin

《Effective C++》学习笔记(八)

原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38962661 条款29:为"异常安全"而努力是值得的 看完这个条款,第一感觉就是之前写的代码多么具有风险. 先看一个书上的例子,假设有个class用来表现夹带背景图案的GUI菜单,这个class也要用于多线程环境当中,所以我们考虑用了一个互斥器(mutex)作为并发控制(concurrency control)之用: class PrettyMenu { p

C++11 现代C++风格的新元素--简介

C++11标准推出了很多有用的新特性,本文特别关注那些相比C++98更像是一门新语言的特性,理由是: 这些特性改变了编写C++程序使用的代码风格和习语[译注 1],通常也包括你设计C++函数库的方式.例如,你会看到更多参数和返回值类型为智能指针(smart pointer),同时也会看到函数通过值传递返回大型对象.你将会发现在大多数的代码示例中充斥着新特性的身影.例如,几乎每5行现代C++代码示例都会使用到auto. C++11的其他特性也很棒.但是请先熟悉下面这些,正是由于这些特性的广泛使用使

C++中类的前置声明和包含头文件的区别

一.类嵌套的疑问 C++头文件重复包含实在是一个令人头痛的问题,假设我们有两个类A和B,分别定义在各自的头文件A.h和B.h中,但是在A中要用到B,B中也要用到A,但是这样的写法当然是错误的: class B; class A{ public: B b;}; class B{ public: A a;}; 因为在A对象中要开辟一块属于B的空间,而B中又有A的空间,是一个逻辑错误,无法实现的,在这里我们只需要把其中的一个A类中的B类型成员改成指针形式就可以避免这个无限延伸的怪圈了,为什么要更改A而

《Effective C++》:条款28-条款29

条款28避免返回handles指向对象内部成分 条款29为异常安全而努力是值得的 条款28:避免返回handles指向对象内部成分 这里的handles指的是引用.指针.迭代器等可以修改对象的传递方法. 假设现在编写一个表示矩形的class,每个矩形有其左上角和右下角表示.先定义平面内的点 class Point{ public: Point(int x, int y); -- void setX(int newVal); void setY(int newVal); -- }; 再定义矩形对象