boost noncopyable类
1. 当声明一个类时,编译器会自动为该类生成默认构造函数,复制构造函数,赋值操作符以及析构函数;
2.自动生成的各个函数和操作符都是public的;
3.当声明一个类不允许复制时,可以将一个类的复制构造函数和赋值操作符声明为private,但是实际中,一般写一个noncopyable类,让不允许使用复制构造函数的类继承于该noncopyable类,boost类就实现了那么一个基类,代码很简单如下:
// Boost noncopyable.hpp header file --------------------------------------// // (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/utility for documentation. #ifndef BOOST_CORE_NONCOPYABLE_HPP
#define BOOST_CORE_NONCOPYABLE_HPP #include <boost/config.hpp> namespace boost { // Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied. // Contributed by Dave Abrahams namespace noncopyable_ // protection from unintended ADL
{
class noncopyable
{
protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
BOOST_CONSTEXPR noncopyable() = default;
~noncopyable() = default;
#else
noncopyable() {}
~noncopyable() {}
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
#else
private: // emphasize the following members are private
noncopyable( const noncopyable& );
noncopyable& operator=( const noncopyable& );
#endif
};
} typedef noncopyable_::noncopyable noncopyable; } // namespace boost #endif // BOOST_CORE_NONCOPYABLE_HPP
模拟:
//
// main.cpp
// nocopy
//
// Created by busyfisher on 13-6-17.
// Copyright (c) 2013年 busyfisher. All rights reserved.
// #include <iostream>
#include <string> class nocopyable{
protected:
nocopyable(){}
~nocopyable(){}
private:
nocopyable(const nocopyable&);
const nocopyable& operator =(const nocopyable&);
}; class person:public nocopyable{
public:
person():age(){}
void set_name(const std::string& str){
name = str;
}
void set_age(const int& _age){
age = _age; }
private:
int age;
std::string name;
}; int main(){ person p1;
p1.set_age();
p1.set_name("Liming"); person p2(p1);<span style="font-family: Arial, Helvetica, sans-serif;">//错误,call to implicitly-deleted copy constructor of 'person'</span><span style="font-family: Arial, Helvetica, sans-serif;">}</span>
nocopyable.cpp: In copy constructor ‘Person::Person(const Person&)’:
nocopyable.cpp:10:2: error: ‘noncopyable::noncopyable(const noncopyable&)’ is private
noncopyable(const noncopyable&);
上面继承不应该是Public,参考下面的:
一个疑惑:
noncopyable类中成员函数只有声明没有定义,行么?
Effective C++
item 06
“为了拒绝编译器自动提供的功能,将相应的函数声明为 private,而且不要给出实现”
网上有版本
C++箴言:拒绝不想用的编译器产生的函数
http://c.chinaitlab.com/cc/ccjq/200808/761013.html
刚试了一下
- class Test {
- void print();
- static void init();
- protected:
- void test();
- public:
- void print(int a) {
- cout << "Test" << endl;
- // init(); 都不可访问, undefined reference
- // print();
- // test();
- }
- // void p(); 声明而不定义undefined reference
- };
复制代码
声明而不定义适用于private及protected的函数,但是public不行
用的Dev-C++,对它们(//注释行)的调用都是linker error,但是仅编译而不连接都可以通过
看来不管访问权限,声明而不定义对编译阶段没有影响,实际的检测是连接阶段
不知道总结得对不对。
C++箴言:拒绝不想用的编译器产生的函数
不动产代理商出售房屋,服务于这样的代理商的软件系统自然要有一个类来表示被出售的房屋:
class HomeForSale { …… };
每一个不动产代理商都会很快指出,每一件财产都是独特的——没有两件是完全一样的。在这种情况下,为 HomeForSale 对象做一个拷贝的想法就令人不解了。你怎么能拷贝一个独一无二的东西呢?最好让这种类似企图拷贝 HomeForSale 对象的行为不能通过编译:
HomeForSale h1; HomeForSale h2; HomeForSale h3(h1); // attempt to copy h1 - should // not compile! h1 = h2; // attempt to copy h2 - should // not compile! |
唉,防止这种编译的方法并非那么简单易懂。通常,如果你不希望一个 class 支持某种功能,你可以简单地不声明赋予它这种功能的函数。这个策略对于拷贝赋值运算符不起作用,因为,就象 Item 5 中指出的,如果你不声明它们,而有人又想调用它们,编译器就会隐式地声明它们。
这就限制了你。如果你不声明拷贝构造函数和拷贝赋值运算符,编译器也可以为你生成它们。你的类还是会支持拷贝。另一方面,如果你声明了这些函数,你的类依然会支持拷贝。我们在这里的目标就是防止拷贝。 解决这个问题的关键是所有的编译器生成的函数都是 public.为了防止生成这些函数,你必须自己声明它们,但是你没有理由把它们声明为 public.相反,应该将拷贝构造函数和拷贝赋值运算符声明为 private.通过显式声明一个成员函数,可以防止编译器生成它自己的版本,而且将这个函数声明为 private,可以防止别人调用它。
通常,这个方案并不十分保险,因为成员函数和友元函数还是能够调用 private 函数。换句话说,除非你不定义它们。那么,当有人不小心地调用了它们,在连接的时候会出现错误。这个窍门——定义一个 private 成员函数却故意不去实现它——确实不错,在 C++ 的 iostreams 库里,就有几个类用此方法防止拷贝。比如,看一下你用的标准库的实现中,ios_base,basic_ios 和 sentry 的定义,你就会看到拷贝构造函数和拷贝赋值运算符被声明为 private 而且没有定义的情况。
将这个窍门用到 HomeForSale 上,很简单:
class HomeForSale { public: .. private: ... HomeForSale(const HomeForSale&); // declarations only HomeForSale& operator=(const HomeForSale&); }; |
你会注意到,我省略了函数参数的名字。这没有必要,只是一个普通的惯例。毕竟,函数不会被定义,极少有机会被用到,有什么必要指定参数的名字呢?
对于上面的类定义,编译器将阻止客户拷贝 HomeForSale 对象的企图,如果你不小心在成员函数或者友元函数中这样做了,连接程序会提出抗议。
将连接时错误提前到编译时间也是可行的(早发现错误毕竟比晚发现好),不要让 HomeForSale 自己去声明 private 的拷贝构造函数和拷贝赋值运算符,在一个特意设计的基类中声明。这个基类本身非常简单:
class Uncopyable { protected: // allow construction Uncopyable() {} // and destruction of ~Uncopyable() {} // derived objects... private: Uncopyable(const Uncopyable&); // ...but prevent copying Uncopyable& operator=(const Uncopyable&); }; |
为了禁止拷贝 HomeForSale 对象,我们必须让它从 Uncopyable 继承:
class HomeForSale: private Uncopyable { // class no longer ... // declares copy ctor or }; // copy assign. operator |
在这里,如果有人——甚至是成员函数或友元函数——试图拷贝一个 HomeForSale 对象,编译器将试图生成一个拷贝构造函数和一个拷贝赋值运算符。就象 Item 12 解释的,这些函数的编译器生成版会试图调用基类的对应函数,而这些调用将被拒绝,因为在基类中,拷贝操作是 private 的。
Uncopyable 的实现和使用包含一些微妙之处,比如,从 Uncopyable 继承不能是 public 的(参见 Item 32 和 39),而且 Uncopyable 的构造函数不必是 virtual 的(参见 Item 7)。因为 Uncopyable 不包含数据,所以它符合 Item 39 描述的空基类优化条件,但因为它是基类,此项技术的应用不能引入多重继承(参见 Item 40)。反过来说,多重继承有时会使空基类优化失效(还是参见 Item 39)。通常,你可以忽略这些微妙之处,而且此处只是用 Uncopyable 来做演示,因为它比较适合做广告。在 Boost(参见 Item 55)中你可以找到一个可用的版本。那个类名为 noncopyable.那是一个好的 class,我只是发现那个名字有一点儿不(un-)……嗯……非自然(nonnatural)。
Things to Remember
·为了拒绝编译器自动提供的功能,将相应的函数声明为 private,而且不要给出实现。使用一个类似 Uncopyable 的基类是方法之一。
class myclass: public boost::noncopyable
{
public:
myclass(){};
myclass(int i){};
}; int main()
{
myclass cl1();
myclass cl2(); // myclass cl3(cl1); // error
// myclass cl4(cl2); // error return ;
}
boost noncopyable类的更多相关文章
- Boost noncopyable实现禁止拷贝的类
在C++中定义一个类,如果不明确定义拷贝构造函数和拷贝赋值操作符,编译期会为我们自动生成这两个函数.但是我们有时又希望禁止拷贝类的实例,这时可以私有化拷贝构造函数和拷贝赋值操作符即可. class d ...
- boost::noncopyable介绍
http://blog.csdn.net/huang_xw/article/details/8248960# boost::noncopyable比较简单, 主要用于单例的情况.通常情况下, 要写一个 ...
- boost::thread类
前言 标准C++线程即将到来.预言它将衍生自Boost线程库,现在让我们探索一下Boost线程库. 几年前,用多线程执行程序还是一件非比寻常的事.然而今天互联网应用服务程序普遍使用多线程来提高与多客户 ...
- boost::noncopyable
/** * boost::noncopyable 实现单例不用麻烦了,直接从这个继承就行了 */ #include <boost/noncopyable.hpp> class myclas ...
- C++ | boost库 类的序列化
是的,这是今年的情人节,一篇还在研究怎么用的文章,文结的时候应该就用成功了. 恩,要有信心 神奇的分割线 不知何时装过boost库的header-only库, 所以ratslam中的boost是可以编 ...
- boost实用工具:创建一个禁止复制的类 noncopyable
boost的noncopyable允许创建一个禁止复制的类,使用很简单,但很好用! C++ Code 12345678910111213141516171819202122232425262728 ...
- [Boost库] noncopyable——禁止拷贝的类
1.noncopyable允许程序轻松地实现一个禁止拷贝的类,在头文件<boost/noncopyable.hpp>中 2.实现原理很简单:noncopyable的实现就是用了C++中 ...
- BOOST 线程完全攻略 - 扩展 - 可被关闭的线程类
本文假设读者已经基本了解boost线程库的使用方法. boost是个开源工程,线程这一块也在不断完善之中,到现在这个阶段,boost::thread仅仅实现了一个完美的技术框架,但是读者在实际使用中会 ...
- (七)boost库之单例类
(七)boost库之单例类 一.boost.serialzation的单件实现 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一 ...
随机推荐
- HBase学习笔记——Java API操作
1.1. 配置 HBaseConfiguration 包:org.apache.hadoop.hbase.HBaseConfiguration 作用:通过此类可以对HBase进行配置 用法实例: C ...
- encoding和charset的区别~
本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难. ...
- [复习] JAVA 遍历目录 (递归调用和非递归)
JAVA 遍历文件夹下的所有文件(递归调用和非递归调用) 1.不使用递归的方法调用. public void traverseFolder1(String path) { int fileNum = ...
- text样式
text-stroke(文本描边)和text-fill-color(文本填充色)注意点: 目前这两个属性只有webkit内核的Safari和Chrome支持,例如: -webkit-text-stro ...
- java 学习笔记--mybatis 三剑客(mybatis)
Java项目中使用Mybatis入门程序 wanna 关注 2017.03.23 14:33* 字数 270 阅读 1243评论 0喜欢 5 MyBatis 是支持定制化 SQL.存储过程以及高级映射 ...
- Storm系统架构以及代码结构学习
转自:http://blog.csdn.net/androidlushangderen/article/details/45955833 storm学习系列:http://blog.csdn.net/ ...
- java算法-数学之美一
巧用数学的思想来解决程序算法问题,这样的代码如诗般优美.通过数学思想来看问题,也能将程序简单化.“斐波那契数列”对于java程序员来说一定不陌生.当然这个问题的解决方案也有很多.用一个例子说明数学思想 ...
- 一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10 (转)
x-ua-compatible 用来指定IE浏览器解析编译页面的model x-ua-compatible 头标签大小写不敏感,必须用在 head 中,必须在除 title 外的其他 meta 之前使 ...
- Linux系统常用工具集
整理Linux系统下一些日常工作中常用工具,旨在提高效率: 1.截图软件Shutter 2.通讯聊天工具pidgin 3.守护进程工具daemontools 4.远程桌面服务TigerVNC 5.Ma ...
- 《linux系统及其编程》实验课记录(一)
实验 1:登录和使用基本的 Linux 命令 实验环境: 安装了 Red Hat Enterprise Linux 6.0 可运行系统,并且是成功验证系统. 有另外一个无特权用户 student,密码 ...