分类: C/C++
2013-02-02 12:06:16
13章内容有点多,分开总结一下。
1. 前面提过,在声明构造函数或考构或某运算符后面加“=delete”,表示此函数不可用。
class base { public: base()= delete; base (const base&) = delete; };如果代码中有直接创建对象或使用拷贝构造函数的代码,编译会失败:
error: use of deleted function 'base::base()'
error: use of deleted function 'base::base(const base&)'
只要不想创建这个类的对象,语法上析构函数也可以声明为delete。
2. 如果是default关键字,则表示我们告诉编译器,直接使用你合成出来的就好。default可以在类外实现时加,但delete只能在类内声明时加。不过像下面这样把delete放在外面,4.6也编过了。但谁有心情把一delete函数搞在外面来写。
class Sales_data { public: Sales_data() = default; }; Sales_data& Sales_data::operator=(const Sales_data&) = default;还有一点,default只能作用在编译器有能力合成的那些函数(con and copy control)和运算符上,delete无此限制。
class base { public: base()=default; void print()=delete; void print()=default; };首先default那行编译会失败:error: 'void base::print()' cannot be defaulted。
注释掉此行,编译OK。由base 对象调用print函数,又会失败:error: use of deleted function 'void base::print()'。
不想复制的类例如IO对象过去是把考构和赋值运算符声明为私有,新标准下,推荐使用delete形式。
3. copy control函数的合成规则
(1)类中某成员的析构函数是delete或私有,则该类的析构编译器会合成为delete;
(2)考构同上;
(3)赋值运算符同上,但多一条:如果类有const成员或者引用类型的成员,赋值运算符会合成为delete
class base { public: base():i3(3){} const int i3 ; }; int main() { base obj; // base obj2 = obj; base obj2; obj2 = obj; cout<<"end in main\n"; return 0; }首先创建对象obj2时不要直接=obj,编译器会优化为使用考构貌似,验证本法则代码要先创建obj2,再赋值。编译器会有如下提示:
test.cpp:60:9: error: use of deleted function 'base& base::operator=(const base&)'
test.cpp:11:7: error: 'base& base::operator=(const base&)' is implicitly deleted because the default definition would be ill-formed:
test.cpp:11:7: error: non-static const member 'const int base::i3', can't use default assignment operator
换成引用也是如此,只不过提示换了,原因是可能改变原引用指向的对象?
non-static reference member 'int& base::i3', can't use default assignment operator
(4)最后看看默认的构造函数,规矩比较多:如果子成员的析构是deleter或私有,则构造为delete,变形金刚的一部分都搞不出来,整体也就没谱了;如果有引用成员,但没有使用类内初始化的形式,默认构造也会为delete,这个反正在4.6没试验出来,非静态成员不让用类内初始化,意思倒好理解,有个引用没初始化,默认构造无法创建;第三,有一个const成员其没有默认构造函数,或者没有对它进行类内初始化,则该类的默认构造也是delete。
总之:子成员无法创建或销毁,整个类就也不能进行。