Item6:Explicitly disallow the use of compiler-generated functions you do not want.
2010-05-11 22:07
513 查看
如果你不想使用编译器自动生成的函数,就明确拒绝
一个描述待售房屋的class:
由于任何一笔资产都是天上地下独一无二,没有二笔完全相像。因此为HomeForSale对象做一份副本有点没有道理。你怎么可以复制某些先天独一无二的东西呢?
通常如果你不希望class支持某一特定功能,只要不声明对应函数就是了。但这个策略对copy构造函数和copy assignment操作符却不起作用,因为条款5已经指出,如果你不声明它们,而某些人尝试调用它们,编译器就会为你声明它们。
关键在于,所有编译器产出的函数都是public。为阻止这些函数被创建出来,你得自行声明它们,但这里并没有什么需求使你必须将它们声明为public。因此你可以将copy构造函数或copy assignment操作符声明为private。
通过声明一个成员函数,你阻止了编译器暗自创建其专属版本;而令这些函数为private,使得你可以成功阻止人们调用它。
一般而言,这个做法并不是绝对安全,因为member函数和friend函数还是可以调用你的private函数。除非你够聪明,不去定义它们,那么如果某些人不慎调用任何一个,会获得一个连接错误(linkage error)。“将成员函数声明为private而且故意不实现它们”这一伎俩是如此为大家接受,因而被用在C++ iostream程序库中阻止copying行为。标准程序库实现代码中的ios_base,basic_ios和sentry的copy构造函数和copy assignment操作符都被声明为private而且没有定义。
将这个伎俩用于HomeForSale也很简单:
有了这个class定义,当客户企图拷贝HomeForSale对象,编译器会阻挠它。如果你不慎在member函数或friend函数之内那么做,连接器报错。
将连接期错误移到编译期是可能的(而且那是好事,毕竟愈早侦测出错误愈好),只要将copy构造函数和copy assignment操作符声明为private就可以办到,但不是在HomeForSale自身,而是在一个专门为了阻止copying动作而设计的base class内。这个base class非常简单:
为了阻止HomeForSale对象被拷贝,我们唯一需要做的就是继承Uncopyable:
只要任何人——甚至是member函数或friend函数——尝试拷贝HomeForSale对象,编译器便试着生成一个copy构造函数和一个copy assignment操作符,正如条款12所说,这些函数的“编译器生成版”会尝试调用其base class的对应兄弟,那些调用会被编译器拒绝,因为其base class的拷贝函数是private。
请记住:
1、为了驳回编译器自动(暗自)提供的功能,可将相应的成员函数声明为private并且不予实现。使用像Uncopyable这样的base class就是一种做法。
一个描述待售房屋的class:
class HomeForSale {...};
由于任何一笔资产都是天上地下独一无二,没有二笔完全相像。因此为HomeForSale对象做一份副本有点没有道理。你怎么可以复制某些先天独一无二的东西呢?
HomeForSale h1; HomeForSale h2; HomeForSale h3(h2); //attempt to copy h1- should not compile h1 = h2; //attempt to copy h2- should not compile!
通常如果你不希望class支持某一特定功能,只要不声明对应函数就是了。但这个策略对copy构造函数和copy assignment操作符却不起作用,因为条款5已经指出,如果你不声明它们,而某些人尝试调用它们,编译器就会为你声明它们。
关键在于,所有编译器产出的函数都是public。为阻止这些函数被创建出来,你得自行声明它们,但这里并没有什么需求使你必须将它们声明为public。因此你可以将copy构造函数或copy assignment操作符声明为private。
通过声明一个成员函数,你阻止了编译器暗自创建其专属版本;而令这些函数为private,使得你可以成功阻止人们调用它。
一般而言,这个做法并不是绝对安全,因为member函数和friend函数还是可以调用你的private函数。除非你够聪明,不去定义它们,那么如果某些人不慎调用任何一个,会获得一个连接错误(linkage error)。“将成员函数声明为private而且故意不实现它们”这一伎俩是如此为大家接受,因而被用在C++ iostream程序库中阻止copying行为。标准程序库实现代码中的ios_base,basic_ios和sentry的copy构造函数和copy assignment操作符都被声明为private而且没有定义。
将这个伎俩用于HomeForSale也很简单:
class HomeForSale { public: ... private: ... HomeForSale(const HomeForSale&); //declaration only HomeForSale operator=(const HomeForsale&); };
有了这个class定义,当客户企图拷贝HomeForSale对象,编译器会阻挠它。如果你不慎在member函数或friend函数之内那么做,连接器报错。
将连接期错误移到编译期是可能的(而且那是好事,毕竟愈早侦测出错误愈好),只要将copy构造函数和copy assignment操作符声明为private就可以办到,但不是在HomeForSale自身,而是在一个专门为了阻止copying动作而设计的base class内。这个base class非常简单:
class Uncopyable { protected: Uncopyable() {} //allow construction and destruction of ~Uncopyable() {} //derived objects... private: Uncopyable(const Uncopyable&); //...but prevent copying Uncopyable& operator=(const Uncopyable&); };
为了阻止HomeForSale对象被拷贝,我们唯一需要做的就是继承Uncopyable:
class HomeForSale: private Uncopyable { ... }; //class no longer declares copy ctor or copy assign. operator
只要任何人——甚至是member函数或friend函数——尝试拷贝HomeForSale对象,编译器便试着生成一个copy构造函数和一个copy assignment操作符,正如条款12所说,这些函数的“编译器生成版”会尝试调用其base class的对应兄弟,那些调用会被编译器拒绝,因为其base class的拷贝函数是private。
请记住:
1、为了驳回编译器自动(暗自)提供的功能,可将相应的成员函数声明为private并且不予实现。使用像Uncopyable这样的base class就是一种做法。
相关文章推荐
- Item 6: Explicitly disallow the use of compiler-generated functions you do not want(Effective C++)
- effective c++ 6: Explicitly disallow the use of compiler-generated functions you do not want
- Item5: Explicitly disallow the use of compiler-generated functions you do not want--若不想使用编译器自动生成的函数,就该明确拒绝
- 6. Explicitly disallow the use of compiler generated functions you do not want
- 【条款6】Explicitly disallow the use of compiler-generated functions you do not want
- 条款6:若不想使用编译器自动生成的函数,就该明确拒绝(Explicity disallow the use of compiler-generated functions you do not want)
- 条款06:若不想使用编译器自动生成的函数,就该明确拒绝(Explicitly disallow the use of compiler-generated you do not want.)
- 《Effective C++》读书笔之六 Item 6. Explicitly disallow the use of compile-generated functions
- 51 You have not configured Oracle Managed Files (OMF) in your database. You do not want to scan the
- 【Datastage】Datastage在win10上安装报错:This Application requires one of the following versions of the .NET Framework:v1.1.4322 Do you want to install this .NET Framework version now?
- 安卓遇到 Do you want to schedule the following file for addition to Subversion? 解决办法
- 驱动程序找不到内核头提示 You do not appear to have the sources for the “kernel version” kernel install 问题
- git push updates were rejected because the remote contain works that you do not have
- 【mysql异常】 InnoDB: Check that you do not already have another mysqld process using the same InnoDB da
- org.apache.hadoop.hbase.DoNotRetryIOException: Class org.apache.phoenix.coprocessor.MetaDataEndpointImpl cannot be loaded Set hbase.table.sanity.checks to false at conf or table descriptor if you want
- OUI-10038:You do not have the necessary permissions to write to the inventory at /oracle/product/ora
- Server Tomcat v7.0 Server at localhost is not responding. Do you want to terminate this server?. Cli
- It appears as though you do not have permission to view information for any of the hosts you request
- The control is not available because you do not have the correct permissions