问题聚焦:
如果不希望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. 如何查看yum安装路径

    #yum install hdf5 #rpm -qa|grep hdf5 hdf5-1.8.7-1.el6.rf.x86_64 #rpm -ql hdf5-1.8.7-1.el6.rf.x86_64

  2. 各种height/width总结

    CSS盒模型是比较复杂的,尤其是当页面中有滚动条时,仅仅通过css来操作高度宽度是不够的,幸运的是Javascript提供了不少这样的接口.Javascript中clientHeight / clie ...

  3. WPF使用Path画圆的一个示例代码

    <Path Fill="red" Data="M 0,0 A 20,20 45 1 1 0,1 Z"/> 1. Fill是指Path的填充颜色 2. ...

  4. Java的接口(interface)属性和方法的类型

    接口的属性必须是public static final Type 接口的方法必须是public abstract Type 不管你是全写,或只写部分,系统都会自动按上面的要求不全 也就是说 接口中 所 ...

  5. Nginx 的信号控制

    摘自:Nginx服务器初识:Nginx启动.停止与信号控制 名称 功能 说明 HUP 重启   QUIT 从容关闭   TERM 快速关闭   INT 从容关闭   USR1 切换日志文件 通常用在切 ...

  6. 分布式版本控制系统Git——使用GitStack+TortoiseGit 图形界面搭建Git环境(服务器端及客户端)(转)

    近期想改公司内部的源码管控从TFS为git,发现yubinfeng大侠有关git的超详细大作,现将其转载并记录下,以防忘记,其原博客中有更加详细的git及.net开发相关内容.原文地址:http:// ...

  7. Scrum 冲刺博客第四篇

    一.当天站立式会议照片一张 二.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中 昨天已完成的工作 新建立了一个list页面用来显示题目,并且创建了列表用来进行题目的存放,将 ...

  8. vue+vuex+axios从后台获取数据存入vuex,组件之间共享数据

    在vue项目中组件间相互传值或者后台获取的数据需要供多个组件使用的情况很多的话,有必要考虑引入vuex来管理这些凌乱的状态,今天这边博文用来记录这一整个的过程,后台api接口是使用webpack-se ...

  9. SQL Serever学习13——数据库编程语言

    编程基础 注释 注释命名来对一些语句进行说明,便于日后维护或者其他用户理解,注释不会执行. 单行注释 SELECT GETDATE() --查询当前日期 多行注释 /* 注释有助于 理解操作的内容 查 ...

  10. C# 多维数组

    int[, ,] shuzu = new int[4, 3, 2]; //有四个二维数组,每个二维数组里面有3个1维数组,每个1维数组里面有2个元素