问题聚焦:
如果不希望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. PHP 对目录下所有TXT进行遍历 并正则进行处理 preg_replace

    <?php set_time_limit(); //遍历 指定目录下的所有 文件/ $pattern是要匹配的 文件规则 function file_list($dir,$pattern=&qu ...

  2. codeblocks 控制台一闪而过

    不要点红的运行,那是调试,点绿色的三角形,那才是运行,不会一闪而过

  3. 思维导图让 Spring MVC 不再难懂

    spring mvc简介与运行原理 Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器 ...

  4. HUE配置文件hue.ini 的impala模块详解(图文详解)(分HA集群)

    不多说,直接上干货! 我的集群机器情况是 bigdatamaster(192.168.80.10).bigdataslave1(192.168.80.11)和bigdataslave2(192.168 ...

  5. java中为什么重写equals时必须重写hashCode方法?

    在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...

  6. PHP之string之addcslashes()函数使用

    addcslashes (PHP 4, PHP 5, PHP 7) addcslashes - Quote string with slashes in a C style addcslashes - ...

  7. SQL语句映射文件(1)resultMap

    SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: ...

  8. Linux笔记-Linux命令初解2

    在看linux过程中,文件属性管理是一个难点,因而作为初学者的我来说,我直接将其放在后面来慢慢研究,因而我个人觉得先学习后面一些知识点之后,回过头来将一些你所不懂的去解透,这是极好的意见事情.对了,我 ...

  9. RocketMQ异常

    rocketMQ下载下来的时候,bin目录下有mqbroker.exe和mqnamesrv.exe两个可执行文件,双击执行都可以成功启动:

  10. PL/SQL之异常

    异常分为预定义异常和用户自定义异常.预定义异常是由系统定义的异常.由于他们已在STANDARD包中预定义了,因此,这些预定义异常可以直接在程序中使用,而不用在预定义部分声明.而用户自定义异常则需要在定 ...