Effective C++(6) 如何拒绝编译器的自动生成函数

摘要:
让我们看一下演示。演示:classUncopyable{protected:Uncopy(){}~Uncopy){}private:Uncopyaable;不可复制的&operator=;};//为了防止自动生成编译,我们唯一需要做的就是继承UncopyableclassHomeForSale:privateUncopyable{…};原则:当试图复制时,编译器将尝试调用父类的相应复制构造函数和重载赋值运算符。这些调用将被编译器拒绝,因为其基类的复制函数是私有的,因此会报告编译错误。参考:EffectiveC++3rd
问题聚焦:
如果不希望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) 如何拒绝编译器的自动生成函数》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android中Handler的使用Javaweb容器的四种作用域下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

iOS开发-Runtime详解(简书)

简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。比如: [receiver message]; // 底层运行时会被编译器转化为: objc_msgSend(receiver, selector) // 如果其还有参数比如: [receiver messag...

c++环境配置

C++ 环境设置本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 文本编辑器 这将用于输入您的程序。文本编辑器包括 Windows Notepad、OS Edit command、Brief、Epsilon、EMACS 和 vim/vi。 文本编辑器的名称和版本在不同的操作系统上可能会有...

gcc编译选项【转】

转自:https://blog.csdn.net/rheostat/article/details/19811407 常用选项 -E:只进行预处理,不编译-S:只编译,不汇编-c:只编译、汇编,不链接-g:包含调试信息-I:指定include包含文件的搜索目录-o:输出成指定文件名 高级选项 -v:详细输出编译过程中所采用的每一个选项-C:预处理时保留注...

#pragma 用法

今天刚开始调试windows核心编程中的例程就感觉十分难懂,原因是自己的c++基本功力实在太弱了 首先在windows编程的过程中大量的使用宏的问题。 #pragma 的用法 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与...

异常(2) --- 编译器对于SEH异常的拓展

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 异常(2) --- 编译器对于SEH异常的拓展 在 异常(1)中,我们介绍了用户模拟异常与CPU异常的收集,以及内核层与用户层异常的处理,其中介绍过SEH异常。 我们之前只提到过编译器拓展SEH异常的,但是由于篇幅有限,并没...

c++ __declspec关键字详细用法

c++ __declspec关键字详细用法       __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式。其它的有关存储方式的修饰符如static与extern等是C和C++语言的ANSI规范,而__declspec是一种扩展属性的定义。扩展属性语法简化并标准化了C和C++语言关于Microsoft的扩展。 用法:__de...