C ++ Primer study note _ 68 _ Object-Oriented Programming

Source: Internet
Author: User

Object-Oriented Programming-constructor and replication control [continued]



Iii. Replication control and inheritance

The merging operation on the objectMember of the base class part and the derived class partTogetherCopy,AssignmentOrUndoUse the base class copy constructor, value assignment operator, or destructor to copy, assign, or revoke the base class.

Whether a replication control member needs to be defined for a class depends entirely on the direct member of the class itself. The base class can define its own copy control, while the derived class uses the merged version. On the contrary, the base class uses the merged version, and the derived class uses its own defined copy control.

The merging operation can be used for classes that only contain data members of the class type or built-in type and classes that do not contain pointers. Copying, assigning, or revoking such members do not require special control. However:Classes with pointer members generally need to define their own replication control to manage these members.!

Copy the base class and then the derived class.



1. Define the copy constructor of the derived class

If the derived class explicitly defines its ownCopy constructorNumber orValue assignment operator,This definition will completely overwrite the default definition.. The copy constructor and the value assignment operator of the inherited class are responsibleBasic ComponentsAndClass MemberCopy or assign values.

If the derived class defines its own copy constructor, the copy constructor generally correspondsExplicitly use the base class copy constructor to initialize the base class of the object:


class Base{public:    //...};class Derived : public Base{public:    Derived(const Derived &d):Base(d)    {        //...    }};

Initialize the function Base (d) to convert the derived class Object dConvert to the reference of its base class,And call the base-class replication constructor..

If the base class initialization function is omitted:

    Derived(const Derived &d)    {        //...    }

The default constructor that runs the Base to initialize the Base class of the object. Assuming that the initialization of the Derived member copies the corresponding member from d, the newly constructed object will have a strange Configuration:ItsBaseSome save the default value,And itsDerivedA member is a copy of another object..



2. Value assignment operator of a derived class

If a derived class defines its own value assignment operator, this operator must explicitly assign values to the base class!

// Base: operator = (const Base &) will not be automatically called, only explicitly called! Derived & operator = (const Derived & rhs) {// The Value assignment operator must prevent itself from assigning values if (this! = & Rhs) {/** the assignment operator of the Base class can be defined by the class or the synthesis assignment operator */Base: operator = (rhs ); // define the assignment operator part of your derived class //...} return * this ;}

3. destructor of the derived class

The work of the Destructor is different from that of the copy constructor and the value assignment operator. The derived class destructor are not responsible for revoking the members of the base class objects. The compiler always explicitly calls the destructor of the base class of the derived class object. Each destructor is only responsible for clearing its own members:

// Automatically call Base ::~ Base ()~ Derived (){//...}

The object revocation order is the opposite to the construction order:First, run the destructor of the derived class.And then call the basic class destructor in turn at the inheritance level!

Constructor&Value assignment operator&Comparison of replication constructor and destructor

Constructor&Value assignment operator&Copy constructor

Destructor

1. Responsible for both the members and the base class [calling the corresponding definition of the base class]

Just take care of your own members.

2. First run the construction of the base class | copy | assign value, and then run

First, run the derived class, and then call

3. cannot be defined as a virtual function

It can be defined as a virtual function.[Generally, it is a virtual function.]



Iv. Virtual destructor

When deleting a pointer to a dynamically assigned object, you must run the destructor inClear objects before releasing the object's memory. When processing objects in the inheritance level, the static type of the pointer may be different from the dynamic type of the object to be deleted, and may be deleted.Actually pointing to a derived class ObjectBase class type pointer.

IfDelete base class pointer, You need to runBase Class destructor and member removal of the base classIf the object is actually of the derived typeThis action is not defined. To run an appropriate destructor, The destructor in the base class must be a virtual function:

class Item_base{public:    virtual ~Item_base() {}    //...};

If the Destructor is a virtual functionCall through pointerWhich destructor will runDifferent types of objects pointed to by pointers!

Item_base * itemP = new Item_base; delete itemP; // call Item_base version itemP = new Bulk_item; // In this case, the pointer's static type is different from the dynamic type delete itemP; // call the Bulk_item version

If the hierarchy is in progressThe root class destructor are virtual functions.,The destructor of the derived class will also be a virtual function.,Whether the derived class explicitly defines the Destructor or uses the synthesis destructor, the derived class destructor are all virtual functions.

The "Three Rules" states that if the class requires destructor, the class almost certainly needs other replication control members. Basic classes almost always require destructor, so that you canSet the Destructor as a virtual functionNumber. If the base class has an empty destructor to set the Destructor as a virtual function,Class with destructorDoes not indicateAlsoValue assignment operatorOrCopy constructor.

[Best practices]

Even if the Destructor has no work to do, the root class at the inheritance level should define a virtual destructor.



Constructor and value assignment operator are not virtual functions

In the replication control member, only the Destructor should be defined as a virtual function, and the constructor cannot be defined as a virtual function.. The constructor runs before the object is fully constructed. When the constructor runs, the object's dynamic type is incomplete!

Setting the value assignment operator of a class to a virtual function may be confusing and will not be of any benefit!

// P496 exercise 15.18: under what circumstances should I have a virtual destructor? /** The class used as the base class should have a virtual destructor: * to ensure that when the base class pointer is deleted (pointing to the dynamically allocated object, * run an appropriate destructor based on the type of the object actually pointed to by the pointer! * For example: */Item_base * itemP = new Bulk_item; delete itemP; // The destructor of Bulk_item needs to be run.

// Exercise 15.20 class Item_base {public: Item_base (const std: string & book = "", double sales_price = 0.0): isbn (book), price (sales_price) {cout <"Item_base (const std: string &, double)" <endl;} Item_base (const Item_base & rhs ); item_base & operator = (const Item_base & rhs); virtual ~ Item_base (); private: std: string isbn; protected: double price;}; Item_base: Item_base (const Item_base & rhs): isbn (rhs. isbn), price (rhs. price) {cout <"Item_base (const Item_base &)" <endl;} Item_base & Item_base: operator = (const Item_base & rhs) {isbn = rhs. isbn; price = rhs. price; cout <"operator = (const Item_base &)" <endl; return * this;} Item_base ::~ Item_base () {cout <"~ Item_base () "<endl;} class Bulk_item: public Item_base {public: Bulk_item (const std: string & book =" ", double sales_price = 0.0, std :: size_t qty = 0, double disc_rate = 0.0): Item_base (book, sales_price), min_qty (qty), discount (disc_rate) {cout <"Bulk_item (const std :: string & book, double, std: size_t, double) "<endl;} Bulk_item (const Bulk_item & rhs); Bulk_item & operator = (const Bulk_item & rhs );~ Bulk_item (); private: std: size_t min_qty; double discount;}; Bulk_item: Bulk_item (const Bulk_item & rhs): Item_base (rhs), min_qty (rhs. min_qty), discount (rhs. discount) {cout <"Bulk_item (const Bulk_item &)" <endl;} Bulk_item & Bulk_item: operator = (const Bulk_item & rhs) {if (this! = & Rhs) {Item_base: operator = (rhs); min_qty = rhs. min_qty; discount = rhs. discount;} cout <"operator = (const Bulk_item &)" <endl; return * this;} Bulk_item ::~ Bulk_item () {cout <"~ Bulk_item () "<endl;} int main () {Item_base * itemP = new Bulk_item; delete itemP; Item_base base; Bulk_item bulk; base = bulk; item_base text (bulk );}

V. virtual functions in constructor and destructor

When constructing a derived class object, first run the base class constructor to initialize the base class of the object. When the base class constructor is executed,The derived class of the object is not initialized.. Actually,At this time, the object is not a derived class Object.

When revoking a derived class object,First, undo its derived class section.And then undo its base class part in the reverse order of the constructor.

In both cases, when you run the constructor or destructor,All objects are incomplete.. To adapt to this incompleteness, the compiler treats the object type as changing during the constructor or destructor. In the base class constructor or destructor, the derived class object is treated as the base class type object!

If you call a virtual function in a constructor or destructorVersion defined for the constructor or destructor type!

class Item_base{public:    Item_base(const std::string &book = "",              double sales_price = 0.0):        isbn(book),price(sales_price)    {        display();    }    virtual ~Item_base()    {        display();    }    virtual void display()    {        cout << "in Item_base!" << endl;    }private:    std::string isbn;    double price;};class Bulk_item : public Item_base{public:    Bulk_item(const std::string &book = "",              double sales_price = 0.0,              std::size_t qty = 0,              double disc_rate = 0.0):        Item_base(book,sales_price),        min_qty(qty),discount(disc_rate)    {        display();    }    void display()    {        cout << "in Bulk_item!" << endl;    }    ~Bulk_item()    {        display();    }private:    std::size_t min_qty;    double discount;};

This binding is applied no matter whether the constructor (or destructor) calls the virtual function directly or indirectly calls the virtual function from the function called by the constructor (or destructor.

[Understanding] What if the base class Constructor (or destructor) calls the derived class version of the virtual function?

The version of the derived class of the virtual function is likely to access the member of the object of the derived class. After all, if the version of the derived class does not need to use the member of the object of the derived class, most of the derived classes can use the definition in the base class. However, the members of the derived part of the object are not initialized during the running of the base class constructor. In fact,If such access is allowed,The program may crash..

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.