问题聚焦:
如果不希望class支持某一成员函数,那么不声明和定义它就可以了,但是这一策略对与拷贝构造函数和重载赋值操作符并不起作用。
因为如果不声明它们,那么当尝试调用它们的时候,编译器会为你声明和定义它们。
这显然不是你所希望看到的。
方法:将这类你不想使用并且也不想编译器为你声明的函数声明为private, 而不实现它们。
原理:
编译器自动生成的函数都是public
声明一个函数可以阻止编译器自动生成该函数
令这个函数为private可以阻止人们调用它

缺陷:

member函数或friend函数可以调用它们,导致链接错误。

Demo:


class HomeForSale {
public:
... ...
private:
...
HomeForSale(const HomeForSale&);
HomeForSale& operator=(const HomeForSale&);
};

上面的方案虽然有一个小小的缺陷,但是还是可以让人接受的,毕竟链接错误不是那么的不可接受。
很多时候我们总是希望尽可能地找到错误,毕竟链接错误远不如编译错误那样相对容易解决一点。
这也是这个方案可以优化的地方(尽管我觉得很多时候可以不这么做)
方案二:在方案一的基础上,将链接期错误移至编译器。
先来看看demo.
Demo:

class Uncopyable {
protected:
Uncopy() {}
~Uncopy() {}
private:
Uncopyable (const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
// 为了阻止编译的自动生成,我们唯一需要做的就是继承Uncopyable class HomeForSale: private Uncopyable {
......
};

原理:
当尝试拷贝操作时,编译器会尝试调用父类的对应的拷贝构造函数和重载赋值操作符,这些调用会被编译器拒绝,因为其base class的拷贝函数是private
从而报出编译错误。

小结:

为了阻止编译器的自动生成功能,可以将相应的成员函数声明为private并且不予实现。
使用向Uncopyable这样的base class也是一种做法。

参考资料:
《Effective C++ 3rd》

Effective C++(6) 如何拒绝编译器的自动生成函数的更多相关文章

  1. NO.6: 若不想编译器提供自动生成的函数,就应该明确拒绝

    1.为驳回编译器自动生成函数的技能,可把这些函数的声明放入private,如果是继承类型可把base class的这些函数声明private,可在编译期间得到警告

  2. C++如何拒绝编译器自动生成的函数

    每一个class,编译器都会自动生成四个特殊成员函数: destructor(析构函数) default constructor(默认构造函数) copy constructor(copy构造函数) ...

  3. C++编译器将自动为类产生四个缺省的函数

    构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意, 其实这些貌似简单的函数就象没有顶盖的下水道那样危险. 每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包 ...

  4. Python使用闭包结合配置自动生成函数

    背景 在构建测试用例集时,常常需要编写一些函数,这些函数接受基本相同的参数,仅有一个参数有所差异,并且处理模式也非常相同.可以使用Python闭包来定义模板函数,然后通过参数调节来自动化生产不同的函数 ...

  5. effective c++ 条款06 不想自动生成函数,就明确拒绝

    编辑器会主动的生成三个/五个函数,如果不需要我们应该主动拒绝 使用私有属性来拒绝 ``` include int main() { return 0; } ``` 使用继承的方式来拒绝

  6. Effective C++ .06 阻止编译器自动生成函数以及被他人调用

    这节讲了下如何防止对象拷贝(隐藏并不能被其他人调用) 两种方法: 1. 将拷贝构造函数声明为private 并且声明函数但不进行定义 #include <iostream> #includ ...

  7. 读书笔记 effective c++ Item 53 关注编译器发出的警告

    许多程序员常常忽略编译器发出的警告.毕竟,如果问题很严重,它才将会变成一个error,不是么?相对来说,这个想法可能在其它语言是无害的,但是在C++中,我敢打赌编译器的实现者对于对接下来会发生什么比你 ...

  8. Effective C++ 条款二 用编译器替换预编译器

    /************************************************************************/ /* C++条款二:用编译器替换预编译器 */ / ...

  9. Effective C++(14) 在资源管理类中小心copying行为

    问题聚焦:     上一条款所告诉我们的智能指针,只适合与在堆中的资源,而并非所有资源都是在堆中的.     这时候,我们可能需要建立自己的资源管理类,那么建立自己的资源管理类时,需要注意什么呢?. ...

随机推荐

  1. graphql pass arg

    ; ; var xhr = new XMLHttpRequest(); xhr.responseType = 'json'; xhr.open("POST", "http ...

  2. java并发编程(10)Fork/Join

    Fork/Join JAVA7中出现的Fork/Join,类似于分布式文件系统hadoop的mapreduce思想,就是将任务分割,再分割,直到分割到满足条件 为了便于理解:编程逻辑可以借用 递归的思 ...

  3. iOS开源项目周报0316

    由OpenDigg 出品的iOS开源项目周报第十二期来啦.我们的iOS开源周报集合了OpenDigg一周来新收录的优质的iOS开源项目,方便iOS开发人员便捷的找到自己需要的项目工具等.GodEye  ...

  4. [转]在windows service中使用timer

    本文转自:http://blog.csdn.net/sharpnessdotnet/article/details/7637180 一定要使用System.Timers.Timer timer 而不是 ...

  5. 远程连接MongoDB数据库

    不使用用户名和密码 安装MongoDB后,默认不使用用户名和密码即可在本地登录,如需远程登录,只要修改/bin/mongo.conf文件即可

  6. c#参数修饰符-out

    out 关键字通过引用传递参数. 方法定义和调用方法必须显式使用out关键字: 调用方法时参数不必初始化,方法内必须对其赋值: 参数中可以声明多个out修饰的参数. 例: public void Us ...

  7. groovy对枚举的支持

    /** * Created by Jxy on 2019/1/3 15:42 * groovy对枚举的支持 */ enum CoffeeSize{ SHORT,SMALL,BIG,MUG } def ...

  8. ubuntu关机重启命令

    重启命令 :     1.reboot     2.shutdown -r now 立刻重启    3.shutdown -r 10 过10分钟自动重启    4.shutdown -r 20:35 ...

  9. 关于Python的那点吐槽

    之前听到过别人有说过Python只是一个玩具做不了大项目,我当时是嗤之以鼻的,不说豆瓣这样的公司采用Python做的网站,GitHub上那么多大项目都是用Python写的,怎么能说Python只是一个 ...

  10. html和css入门 (一)

    HTML简介 什么是HTML HTML 的全称为 超文本标记语言(Hyper Text Markup Language),这种语言给我们提供一种建立结构性文档的方法.通过表示结构性的标签语法,我们可以 ...