Effective C++ -- 构造析构赋值运算
2015-03-14 22:29
197 查看
05.了解C++默默编写并调用哪些函数
编译产生的析构函数时non-virtual,除非这个类的基类析构函数为virtual成员变量中有引用和const成员时,无法自动生成copy assignment函数
基类将copy assignment操作符声明为private时,编译器拒绝为其derived classes生成一个copy assignment操作符。
06.若不想使用编译器自动生成的函数,就该明确拒绝
将自动生成的默认构造函数,拷贝构造函数,copy assignment声明为private声明为private并不绝对安全,成员函数和友元函数可以进行调用 -- 进行声明,但不定义(产生链接错误)
定义一个基类,将默认构造函数,拷贝构造函数,copy assignment声明为private,由派生类继承该基类(产生编译错误,boost中的noncopyable类)
07.为多态基类声明virtual析构函数
基类指针指向派生类时,delete基类指针,无法调用到派生类的析构函数任何class只要带有virtual函数,应该有一个virtual析构函数。
当class不含virtual函数,通常表示它并不意图被用作一个base class。
当class不企图被当做base class,其析构函数为virtual往往是个馊主意。(占用空间,降低效率)
08.别让异常逃离析构函数
析构函数未捕获异常时,如果该类对象存储于容器中,产生异常后可能导致容器中的其他对象无法析构。析构函数需要捕获异常,某些引发异常的操作可移出析构,由客户调用进行处理
09.绝不在构造和析构中调用virtual函数
base class构造期间,virtual函数绝不会下降到derived class阶层。构造期间,virtual函数不是virtual函数。当base class构造函数执行时derived class成员变量尚未初始化,如果下降到derived class,derived class将会使用为初始化的local成员变量。
derived class对象的base class构造期间,对象的类型时base class。
一旦derived class析构函数开始执行,进入base class析构函数后,对象类型被视为base class。
10.令operator=返回一个reference to *this
为了实现连锁赋值,赋值操作符必须返回一个reference指向操作符左侧实参。只是协议,并非强制。Widget& operator=(const Widget& rhs) {return *this;}
问题:
是否可以返回常量引用?
11.在operator= 中处理自我赋值
需要解决自我赋值安全性和异常安全性class Bitmap {...};
class Widget {
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
};
以上代码问题:当自我赋值时,将删除自身的pb。构造新bp时,使用一个已删除的对象。解决方法如下:
Widget& Widget::operator=(const Widget& rhs)
{
if (this == &rhs)
return *this;
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
以上代码存在问题:new Bitmap导致异常时,pb指向一个已删除的区域。解决方法如下:
Widget& Widget::operator=(const Widget& rhs) { if (this == &rhs) return *this; Bitmap* pOrig = pb; pb = new Bitmap(*rhs.pb); delete pOrig; return *this; }
12.复制对象时勿忘其每一个成分
新添加成员变量时需要修改复制构造函数,copy assignment函数。class PriorityCustomer: public Customer {
public:
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
private:
int priority;
};
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):priority(rhs.priority)
{
log("");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
log("");
priority = rhs.priority;
return *this;
}
以上代码问题:未调用基类的拷贝构造函数,未调用基类的赋值操作符重载函数。正确代码如下:
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs):Customer(rhs),priority(rhs.priority)
{
log("");
}
PriorityCustomer& PriorityCustomer::operator=(const PriorityCustomer& rhs)
{
log("");
Customer::operator(rhs);
priority = rhs.priority;
return *this;
}
无法在拷贝构造函数中调用基类的赋值操作符重载,无法在赋值操作符重载函数中调用基类的拷贝构造函数。
相关文章推荐
- effective c++ 第二部分(构造析构赋值运算)
- Effective C++ —— 构造/析构/赋值运算(二)
- effective c++-构造/析构/赋值运算
- effective C++之构造、析构、赋值运算
- 《Effective C++》 读书笔记之二 构造/析构/赋值运算
- 【读书笔记】Effective C++-2 构造/析构/赋值运算(之四)
- 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记
- Effective C++之构造、析构、赋值运算
- Effective C++之2 构造/析构/赋值运算
- Effective C++ 笔记 第二部分 构造/析构/赋值运算
- effective C++之构造、析构、赋值运算
- Effective C++ —— 构造析构赋值
- Effective C++学习笔记——构造/析构/拷贝运算
- [Effective C++]构造/析构/赋值运算
- effective c++之构造 析构 赋值运算
- 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记
- 【读书笔记】Effective C++-2 构造/析构/赋值运算(之一)
- 《Effective C++》第2章 构造/析构/赋值运算(2)-读书笔记
- 【effective c++】构造/析构/赋值运算
- Effective C++(二)构造/析构/赋值运算