条款05:了解C++默默编写了并调用了那些函数
编译器会声明一个copy构造函数,一个copy assignment 操作符合一个析构函数所有这些函数都是public和inline的
如果打算在一个内含reference 成员的class内支持赋值操作你必须自己定义copy assignment 操作符面对const成员的classes编译器反应也一样。
另一种情况:如果某个base class将assignment操作符声明为private编译器将拒绝为derived class 生成一个copy assignment 操作符
请记住
@编译器可以暗自为class 创建default构造函数,copy构造函数,copy assignment 操作符,以及析构函数
条款06 如果不想使用编译器自动生成的函数就应该明确的拒绝
有个class 用来描述待售房
class HomeForSale{};
任何一笔资产都是独一无二的那么该class不该存有副本
HomeForSale h1;
HomeForSale h2;
HomeForSale h3(h1)//企图拷贝h1 ----编译不应该通过
h1=h2;/编译不应该通过
为解决以上问题
可以讲copy构造函数和copy assgiment 操作符声明为private来阻止编译器暗自创建其专属版本。但这也不是绝对的安全因为member函数和friend函数还是可以调用你的private函数。最好的方法是不去定义他们即将成员函数声明为private而且故意不提供实现他们。
那么HomeForSale可以这样的改写
class HomeForSale{
private:
HomeForSale(const HomeForSale&);//只是声明不去实现
HomeForSale& operator=(const HomeForSale&);//同上
};
很多情况下我们专门设计一个阻止copying动作的base class像这样
class Uncopyable{
proctected:
Uncopyable(){}
~Uncopyable(){}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
其他类只需继承此类便可获取阻止copying行为(boost 库提供 class noncopyable来实现阻止copying行为)
请记住:
@为驳回编译自动(暗自)提供的机能,可将相应成员函数声明为private并且不予以实现.使用像Uncopyable这样的base class 也是一种做法
条款07:为多态的基类,声明virtual析构函数
class TimeKeeper{
public:
TimeKeeper();
~TimeKeeper();
};
class AtomicClock:public TimeKerrper{...}
class WaterClock:public TimeKeeper{...}
我们这样的到对象指针:
TimeKeeper* getTimeKeeper();//指向一个派生类动态分配的对象指针
TimeKeeper*ptk=getTimeKeeper();
delete ptk;
以上会导致一些问题C++明白的指出当derived对象经由一个base class 指针删除时而该base class带着一个non-virtual 析构函数那么结果是未有定义的通常不会释放derive的成分
消除问题很简单为base class 提供一个virual 析构函数
但如果class 不含vitual函数那么通常情况下他并不意图被当做一个base class 如果令其析构函数为virtual 那么行为也将是糟糕的因为含有virtual函数的对象其内部维护了一个vptr指针其对象将会比一般不带virual函数的对象要大
还有一个问题需注意:
class SpecialString:public string//string有个non virual析构函数
{
};
如果你在程序中无意间将一个pointer to SpecialString转化为一个pointer to string然后delete掉,就会出现行为不明确
string有个non virual析构函数
有时候让class带一个pure virtual 析构函数可能会更加的便利(同时要为此析构函数提共一份定义否则编译器会抱怨的)
class AWOV
{
public:
virtual ~AWOV()=0;
};
AWOV::~AWOV(){}
上面这种情况只适用于带多态性质的base class 身上
请记住:
@polymorphic(带多态性质的)base class 应该声明一个virtual析构函数如果class带有任何virtual 函数,他就该拥有一个virtual析构函数.
@Classes 的设计目的如果不是作为base class 适用,或者不是为了具备多态性质就不该声明为virual析构函数