C++ Chapter 2. Constructors, Destructors, and Assignment Operators

 1.compilers will declare their own versions of a copy constructor, a copy assignment operator, and a destructor. Furthermore, if you declare no constructors at all, compilers will also declare a default constructor for you. All these functions will be bothpublic and inline

These functions are generated only if they are needed(when they are called)

Note that the generated destructor is non-virtual (seeItem7) unless it's for a class inheriting from a base class that itself declares a virtual destructor (in which case the function's virtualness comes from the base class).


2.If you want to support assignment in a class containing a reference member, you must define the copy assignment operator yourself. Compilers behave similarly for classes containing const members (such asobjectValue in the modified class above). It's not legal to modify const members, so compilers are unsure how to treat them during an implicitly generated assignment function. 

Finally, compilers reject implicit copy assignment operators in derived classes that inherit from base classes declaring the copy assignment operatorprivate. Because compiler-generated copy assignment operators for derived classes are supposed to handle base class parts, too (seeItem 12), but in order to do so, they certainly can't invoke member functions(private copy assignment operators in base class) the derived class has no right to call.


3.declare the copy constructor and the copy assignment operator private and deliberately not implementing them can prevent default functions from being generated.


4. C++ specifies that when a derived class object is deleted through a pointer to a base class with a non-virtual destructor, results are undefined

You need to define a virtual destructor for the base class in Polymorphism(only in polymorphism where base classes designed to allow the manipulation of derived class types through base class interfaces ) so that the derived class can delete(base class pointer point to derived class object) their object totally, or only the base class destructor will be called. 

declare a virtual destructor in a class if and only if that class contains at least one virtual function.

C++ specifies that when a derived class object is deleted through a pointer to a base class with a non-virtual destructor, results are undefined.

we can create a pure virtual destructor in base class but we need to provide a definition for it because it will be called by derived class destructor.

class AWOV {                            // AWOV = "Abstract w/o Virtuals"

public:

  virtual ~AWOV() = 0;                  // declare pure virtual destructor

};


This class has a pure virtual function, so it's abstract, and it has a virtual destructor, so you won't have to worry about the destructor problem. There is one twist, however: you must provide adefinition for the pure virtual destructor:

AWOV::~AWOV() {}                     // definition of pure virtual    dtor


5.Destructors should never emit exceptions. If functions called in a destructor may throw, the destructor should catch any exceptions, then swallow them or terminate the program.

  • If class clients need to be able to react to exceptions thrown during an operation, the class should provide a regular (i.e., non-destructor) function that performs the operation.

class DBConn {

public:

  ...



  void close()                                     // new function for

  {                                                // client use

    db.close();

    closed = true;

  }



  ~DBConn()

   {

   if (!closed) {

   try {                                            // close the connection

     db.close();                                    // if the client didn't

   }

   catch (...) {                                    // if closing fails,

     make log entry that call to close failed;   // note that and

     ...                                             // terminate or swallow

   }

  }



private:

  DBConnection db;

  bool closed;

};


6. Don't call virtual functions during construction or destruction, because such calls will never go to a more derived class than that of the currently executing constructor or destructor.

There are different ways to approach this problem. One is to turn logTransaction into a non-virtual function intransaction, then require that derived class constructors pass the necessary log information to theTRansaction constructor. That function can then safely call the non-virtuallogTransaction. Like this:

class Transaction {

public:

  explicit Transaction(const std::string& logInfo);



  void logTransaction(const std::string& logInfo) const;   // now a non-

                                                           // virtual func

  ...

};



Transaction::Transaction(const std::string& logInfo)

{

  ...

  logTransaction(logInfo);                                // now a non-

}                                                         // virtual call



class BuyTransaction: public Transaction {

public:

 BuyTransaction( parameters )

 : Transaction(createLogString( parameters ))             // pass log info

  { ... }                                                 // to base class

   ...                                                    // constructor



private:

  static std::string createLogString( parameters );

};


7. Have assignment operators return a reference to*this


8. Make sure operator= is well-behaved when an object is assigned to itself. Techniques include comparing addresses of source and target objects, careful statement ordering, and copy-and-swap.

Make sure that any function operating on more than one object behaves correctly if two or more of the objects are the same.

Carefully statement Ording
Widget& Widget::operator=(const Widget& rhs)

{

  Bitmap *pOrig = pb;               // remember original pb

  pb = new Bitmap(*rhs.pb);         // make pb point to a copy of *pb

  delete pOrig;                     // delete the original pb



  return *this;

}


Copy and Swap

class Widget {

  ...

  void swap(Widget& rhs);   // exchange *this's and rhs's data;

  ...                       // see Item 29 for details

};



Widget& Widget::operator=(const Widget& rhs)

{

  Widget temp(rhs);             // make a copy of rhs's data



  swap(temp);                   // swap *this's data with the copy's

  return *this;

}


A variation on this theme takes advantage of the facts that (1) a class's copy assignment operator may be declared to take its argument by value and (2) passing something by value makes acopy of it (seeItem 20):

Widget& Widget::operator=(Widget rhs)   // rhs is a copy of the object

{                                       // passed in — note pass by val



  swap(rhs);                            // swap *this's data with

                                        // the copy's



  return *this;

}


9.

int* set = new int[100];
//use set[]
delete [] set;

10. When you're writing a copying function, be sure to (1) copy all local data members and (2) invoke the appropriate copying function in all base classes, too.

  • Copying functions should be sure to copy all of an object's data members and all of its base class parts.

  • Don't try to implement one of the copying functions(copy constructor and copy assignment operator) in terms of the other. Instead, put common functionality in a third function that both call.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值