effective C++之构造、析构、赋值运算

条款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析构函数






猜你喜欢

转载自blog.csdn.net/luguifang2011/article/details/42879643