1. 说明
在上一篇的示例中在说明封装抽象类时有用到boost::noncopyable类,在实际使用的很多情况下,加没加这个类似乎对我的操作没有影响,那么这个类到底有什么作用呢,在这篇笔记中详细分析一下。
1.1 noncopyable作用
其官方说明是:Private copy constructor and copy assignment ensure classes derived from class noncopyable cannot be copied.大意是将私有化类的拷贝构造函数和拷贝赋值操作符,这样子类可以调用,但是外部调用者不能通过复制/赋值等语句来产生一个新的对象。
boost::noncopyable主要的用法是作为父类供其他类继承其特性。
2. 示例
这里定义了两个类Test1和Test2,其中Test2继承boost::noncopyable的特性
#include <iostream>#include <boost/noncopyable.hpp>class Test1 {
public:Test1(int i) {
std::cout << "This is Test1 that is copyable" << std::endl;}
};class Test2 : boost::noncopyable {
public:Test2(int i) {
std::cout << "This is Test2 that is noncopyable" << std::endl;}
};int main()
{
Test1 t1(1);Test2 t2(2);Test1 t3 = t1; // It's OKTest1 t4(t1); // It's OKTest2 t5 = t2; // Cannot be referencedTest2 t6(t2); // Cannot be referencedTest2 &t7 = t2; // It's OKreturn 0;
}
直接编译时会报错,如下:
g++ test.cpptest.cpp: In function ‘int main()’:
test.cpp:23:16: error: use of deleted function ‘Test2::Test2(const Test2&)’23 | Test2 t5 = t2; // Cannot be referenced| ^~
test.cpp:10:7: note: ‘Test2::Test2(const Test2&)’ is implicitly deleted because the default definition would be ill-formed:10 | class Test2 : boost::noncopyable {
| ^~~~~
test.cpp:10:7: error: use of deleted function ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’
In file included from /usr/local/include/boost/noncopyable.hpp:15,from test.cpp:3:
/usr/local/include/boost/core/noncopyable.hpp:49:7: note: declared here49 | noncopyable( const noncopyable& ) = delete;| ^~~~~~~~~~~
test.cpp:24:16: error: use of deleted function ‘Test2::Test2(const Test2&)’24 | Test2 t6(t2); // Cannot be referenced
从编译信息可以看出,Test2不支持使用复制的方式来实例化类。
3. boost::noncopyable类详解
boost::noncopyable定义在 <boost/core/noncopyable.hpp> 中。定义如下:
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.// Contributed by Dave Abrahamsnamespace noncopyable_ // protection from unintended ADL
{
#ifndef BOOST_NONCOPYABLE_BASE_TOKEN_DEFINED
#define BOOST_NONCOPYABLE_BASE_TOKEN_DEFINED// noncopyable derives from base_token to enable Type Traits to detect
// whether a type derives from noncopyable without needing the definition
// of noncopyable itself.
//
// The definition of base_token is macro-guarded so that Type Trais can
// define it locally without including this header, to avoid a dependency
// on Core.struct base_token {
};#endif // #ifndef BOOST_NONCOPYABLE_BASE_TOKEN_DEFINEDclass noncopyable: base_token{
protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)BOOST_CONSTEXPR noncopyable() = default;~noncopyable() = default;
#elsenoncopyable() {
}~noncopyable() {
}
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)noncopyable( const noncopyable& ) = delete;noncopyable& operator=( const noncopyable& ) = delete;
#elseprivate: // emphasize the following members are privatenoncopyable( const noncopyable& );noncopyable& operator=( const noncopyable& );
#endif};
}typedef noncopyable_::noncopyable noncopyable;} // namespace boost
注意其中的关键语句:
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)noncopyable( const noncopyable& ) = delete;noncopyable& operator=( const noncopyable& ) = delete;
#elseprivate: // emphasize the following members are privatenoncopyable( const noncopyable& );noncopyable& operator=( const noncopyable& );
#endif
BOOST_NO_CXX11_DELETED_FUNCTIONS
类重载了复制和"=“运算符,将它们变为"delete”。上面的语句中如果没有定义BOOST_NO_CXX11_DELETED_FUNCTIONS
类,那么直接实现了重载运算符的功能,如果有定义,则将这两个运算符变成私有成员。即无论如何,noncopyable类下复制和"="运算符都被重载为"delete"了。
参考资料
https://www.boost.org/doc/libs/1_78_0/libs/core/doc/html/core/noncopyable.html