`
897371388
  • 浏览: 522161 次
文章分类
社区版块
存档分类
最新评论

《Effective C++》Item6: 如果你不想使用编译器生成的函数,就该明确拒绝!

 
阅读更多
通过对item5的学习我们知道:编译器会暗自为class创建default构造函数、copy构造函数、copy assignment操作符以及析构函数。
but,有时候我们不希望我们的类有某些特定功能,通常的做法就是不声明具有这些功能的函数就可以了,however,对于某些与生俱来的功能——比如copy构造和copy assignment,即使我们不声明,系统也会自动生成。
解决办法是可以在类中声明copy构造函数和copy assignment操作符,但并不实现这些函数,并将其声明为private,这样就可以阻止编译器自动生成默认函数,又可以阻止别人调用这些功能。

例如:

// PrivateConstructor.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class HomeForSale
{
private:
	HomeForSale(const HomeForSale&);            //声明一个copy构造函数,并不实现它,连变量名字都没有起
	HomeForSale& operator=(const HomeForSale&); //声明一个copy assignment操作符,并不实现它

	double price;
	double area;
public:
	HomeForSale(double price, double area):price(price),area(area){}
};

int _tmain(int argc, _TCHAR* argv[])
{
	HomeForSale home(1000, 2000);
	HomeForSale home1(home); //error:无法访问 private 成员(在“HomeForSale”类中声明)
	HomeForSale home2 = home;//error:无法访问 private 成员(在“HomeForSale”类中声明)
	return 0;
}

编译的时候就会报出“error C2248: “HomeForSale::HomeForSale”: 无法访问 private 成员(在“HomeForSale”类中声明)”这样的错误!

有了这样的声明(而不是定义),当客户企图拷贝HomeForSale对象时,编译器就会阻止他,如果不慎在类的其他成员函数或者friend函数中做了这样的事,就会出现link error。

以下方法可以将连接错误移至编译期:

// PrivateConstructor.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

using namespace std;

class Uncopyable
{
protected:
	Uncopyable(){}
	~Uncopyable(){}
private:
	Uncopyable(const Uncopyable&);
	Uncopyable& operator=(const Uncopyable&);
};

class HomeForSale: private Uncopyable
{
private:
	double price;
	double area;
public:
	HomeForSale(double price, double area):price(price),area(area){}
};

int _tmain(int argc, _TCHAR* argv[])
{
	HomeForSale home(1000, 2000);
	//HomeForSale home1(home); //error:无法访问 private 成员(在“HomeForSale”类中声明)
	//HomeForSale home2 = home;//error:无法访问 private 成员(在“HomeForSale”类中声明)
	return 0;
}

根据item5我们知道:如果某个base class将copy assignment操作符声明为private,编译器将拒绝为其derived classes生成一个copy assignment操作符,因为如果生成了,那么derived classes中的copy assignment操作符就必须能够调用base class中的copy assignment操作符进行处理继承下来的base class中的成员,而base class中的copy assignment操作符被声明成了private的,无法调用,所以相互矛盾。







分享到:
评论

相关推荐

    Effective C++条款06:构造/析构/赋值运算之(若不想使用编译器自动生成的函数,就该明确拒绝)

    一、前言 在前面一篇文章中(https://blog.csdn.net/qq_41453285/article/details/104165762),我们介绍了C++编译器...如果我们不想使用某些函数,将这些不想使用的函数在类中声明为private,那么就不能使用这些函数了

    Effective C++ 中文版

    条款06:若不想使用编译器自动成生的函数,就该明确拒绝 条款07:为多态基类声明Virtual析构函数 条款08:别让异常逃离析构函数 条款09:绝不在构造和析构过程中调用Virtual函数 条款10:令Operator=返回一个...

    Effective C++

    条款27:如果不想使用隐式生成的函数要显示的禁止它 条款28:划分全局名字空间 4、类和函数:实现 条款29:避免返回内部数据的句柄 条款30:避免这样的成员函数,其返回值是指向成员的非CONST指针或引用 条款31:千万不要...

    More Effective C++

    只有深刻了解 C++ 编译器如何解释你的码,你才有可能以 C++ 语言写出稳健强固的软体。本书是协助你获得此等层级之了解过程中,一份极具价值的资源。读过本书之後,我感觉像是浏览了 C++ 程式大师所检阅过的码,并...

    More Effective C++中文版

    一些经过验证的用来改善程序效率的方法,包括检验C++语言特性所带来的时间和空间上的成本。  全面地描述了C++专家所使用的高级技术,包括...如果你的编译器不支持这些特性,本书还介绍了如何不利用它们完成工作。

    Effective.C++.中文第二版.50条款doc文档.chm

    条款27: 如果不想使用隐式生成的函数就要显式地禁止它 条款28: 划分全局名字空间 第五章 类和函数: 实现 条款29: 避免返回内部数据的句柄 条款30: 避免这样的成员函数:其返回值是指向成员的非const指针或引用,但...

    Effective C++(第三版)

    条款06:若不想使用编译器自动生成的函数,就该明确拒绝 explicitly disallow the use of compiler-generated functions you do not want. 条款07:为多态基类声明virtual析构函数 declare destructors virtual in ...

    more effective c++

    一些经过验证的用来改善程序效率的方法,包括检验C++语言特性所带来的时间和空间上的成本。, 全面地描述了C++专家所使用的高级技术,包括...如果你的编译器不支持这些特性,本书还介绍了如何不利用它们完成工作。

    Effective C++之2.构造析构赋值运算

    条款06:如不想使用编译器自动生成的函数,就应该明确拒绝 为了驳回编译器暗自提供的机能,可将相应的成员函数声明为private并且不予实现。使用像Uncopyable这样的base class 也是一种做法。不过C++11开始,可以用...

    浅谈C++ Explicit Constructors(显式构造函数)

    C++ 为类(Class)提供了许多默认函数。如果自己没有申明,编译器会为我们提供一个copy构造函数、一个copy assignment操作符和一个析构...就像Effective C++说的,如果不想使用编译器自动生成的函数,就应该明确拒绝。 1

    Effective STL(中文)

    &lt;br&gt;《Effective STL》目录: &lt;br&gt;前言 致谢 导读 容器 条款1:仔细选择你的容器 条款2:小心对“容器无关代码”的幻想 条款3:使容器里对象的拷贝操作轻量而正确 条款4:用empty来代替...

    effective stl 中文 pdf

    条款6: 警惕C++的及其令人恼怒的分析 条款7: 当使用new得指针的容器时,切记在容器销毁前delete那些指针 条款8: 千万不要把auto_ptr放入容器中 条款9: 小心选择删除选项 条款10: 当心allocator的协定和约束 ...

    effective stl stl 技巧

    条款32:如果你真的想删除东西的话就在类似remove的算法后接上erase 条款33:提防在指针的容器上使用类似remove的算法 条款34:注意哪个算法需要有序区间 条款35:通过mismatch或lexicographical比较实现简单的...

    Effective C++条款12:构造/析构/赋值运算之(复制对象时勿忘其每一个成份)

    我们在前面文章已经介绍了,如果类没有手动声明拷贝构造函数或拷贝赋值运算符,那么编译器会为我们自动生成这两个成员,并且它们的行为是:将被拷贝的对象的所有成员做一份拷贝 二、复制对象时确保复制所有成员 下面...

    Effictive STL CHM中文版

    条款6: 警惕C++的及其令人恼怒的分析 条款7: 当使用new得指针的容器时,切记在容器销毁前delete那些指针 条款8: 千万不要把auto_ptr放入容器中 条款9: 小心选择删除选项 条款10: 当心allocator的协定和约束 ...

    代码语法错误分析工具pclint8.0

    Windows平台下也有好多人都喜欢用SourceInsight编辑C/C++程序,如果将pclint集成到SourceInsight中,那就相当于给SourceInsight增加了一个C/C++编译器,而且它的检查更严格,能发现一些编译器发现不了的问题,可以...

    10个精妙的Java编码佳实践

    这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表。和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不常见的情况,可能有很大影响。  我在编写和维护...

    modern_cpp_training:我的个人现代C ++动手培训

    此仓库是我围绕Scott Meyers的“ Effective Modern C ++”进行的动手实践培训。 每个项目都涵盖了一个我发现很重要的主题,我想尝试一下。 大部分代码是原始代码,但是,还有一些其他网站示例中的复制粘贴,例如...

Global site tag (gtag.js) - Google Analytics