05 :了解C++默默编写并调用哪些函数
空类Empty class,C++处理之后,如果你没有自己声明,编译器就会它声明一个拷贝构造函数,拷贝赋值函数和析构函数,甚至是default构造函数。所有这些函数都是public且inline的。
如果你写了,
class Empty{ };
经过C++处理后相当于:
class Empty{
public:
Empty(){...}; //default构造函数
Empty(const Empty& rhs){..}; //copy构造函数
~Empty(){...}; //析构函数,是否为Virtual?
Empty& operator=(const Empty& rhs){} //copy assignment操作符
}:
惟有当这些函数被需要(被调用),它们才会被编译器创建出来。下面代码造成上述每一个函数被编译器产出:
Empty el; //default构造函数
//析构函数
Empty e2(e1); //copy构造函数
e2 = el; //copy assignment操作符
总结:
编译器暗自为class创建default构造函数,copy构造函数,析构函数和copy assignments操作符。
06: 若不想使用编译器自动生成的函数,就该明确拒绝。
该条款是针对条款05的解决办法!!!
因为条款05已经指出,如果你不声明它们,而某些人尝试调用它们,编译器会为你声明它们。
如果你不声明copy
构造函数或copy assignment
操作符,编译器可能为你产出一份,于是你的class
支持copying
。如果你声明它们,你的class
还是支持copying
。但这里的目标却是要阻止copying
!
做法:
-
为了不使用编译器自动提供创建函数的功能,可将相应的成员函数,将
copy
构造函数或copy assignment
操作符声明为private
并且不予实现。 -
使用像
Uncopyable
这样的base class
也是一种做法。
class HomeForSale {
public:
...
private:
...
HomeForSale (const HomeForsale& ) ; //只有声明
HomeForsale & operator- (const HomeForSale& ) ;
};
有了上述class
定义,当客户企图拷贝HomeForSale
对象,编译器会阻挠他。如果你不慎在member
函数和friend
函数之内那么做,轮到连接器发出抱怨。
一般而言这个做法并不绝对安全,因为member
函数和friend
函数还是可以调用你的private
函数。除非不去定义它们,那么如果某些人不慎调用任何一个,会获得一个连接错误(linkage error)。
改进方法:
//Uncopyable实现阻止编译器自动创建函数
class Uncopyable{
protected:
Uncopyable(){};
~Uncopyable(){};
private:
Uncopyable(const Uncopyable&); //阻止copy构造函数
Uncopyable& operator=(const Unconpyable&);
}
//为了防止HomeSale对象被拷贝,通过继承Uncopyable类便可以避免
class Homesale: private Uncopyable{
... //class将不再自动声明 copy构造函数以及copy assignment操作符。
...
}