您的位置:首页 > 编程语言 > C语言/C++

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

2012-04-03 12:09 447 查看
 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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息