Constructor and replication control of a derived class

Source: Internet
Author: User

Because a derived class is inherited from a base class, it contains some members of the base class. Therefore, when writing the constructor and replication control function of the derived class, you must consider the impact of the base class.

First, the constructor. In the constructor of a derived class, the constructor does not directly initialize the members of the base class, but calls the constructor of the base class to initialize the base class:

Class item_base {public: // constructor item_base (const STD: string & book = "", double sales_price = 0.0): ISBN (book), price (sales_price) {STD:: cout <"base class constructor" <STD: Endl;} // returns the ISBN number STD: String book () {return ISBN ;} // The base class does not require the discount policy virtual double net_price (STD: size_t N) const {return N * price;} // destructor virtual ~ Item_base () {STD: cout <"base class destructor" <STD: Endl ;}; // The replication control function item_base (const item_base &); // value assignment operation item_base & operator = (const item_base &); Private: STD: String ISBN; protected: Double price ;}; class bulk_item: Public item_base {public: // const STD: string & book = "", double sales_price = 0.0, STD: size_t qty = 0, double disc_rate = 0.0): item_base (book, sales_price), quantity (qty), discount (disc_rate) {STD: Co Ut <"derived class constructor" <STD: Endl ;}~ Bulk_item () {STD: cout <"derived class destructor" <STD: Endl;} double net_price (STD: size_t) const; // copy control bulk_item (const bulk_item &); // value assignment operator bulk_item & operator = (const bulk_item &); Private: STD: size_t quantity; double discount ;};

In addition, each time the base class is initialized, the members of the derived class are initialized. Note that a derived class can only initialize its own base class, and does not need to consider how to initialize the base class of the base class.

For the replication control function, let's look at it one by one:

Let's talk about the replication constructor. It defines what happens when a derived class object is copied to another derived class object. It also needs to complete two parts: Call the copy constructor of the base class to complete the copy of the base class, and then copy the part of the derived class.

// Base-class replication control item_base: item_base (const item_base & Ib) {ISBN = IB. ISBN; Price = IB. price; STD: cout <"base class replication constructor" <STD: Endl ;}

 

// Copying constructor from a derived class: bulk_item (const bulk_item & B): item_base (B); {quantity = B. quantity; Discount = B. discount; STD: cout <"derived class copy constructor" <STD: Endl ;}

Note the scope OPERATOR: If the scope identifier is not added, you will be prompted to redefine the form parameter B. Because item_base (B) is equivalent to creating an item_base object B, it is redefined. After the scope operator is used, it means that the replication constructor item_base of the base class is called, and the base class is copied directly with the derived class, so no redefinition will appear.

Similarly, there are assignment operators:

// Item_base & item_base: Operator = (const item_base & RHs) {ISBN = RHS. ISBN; Price = RHS. price; STD: cout <"base class assignment operator" <STD: Endl; return * This ;}
// Value assignment operator bulk_item & bulk_item: Operator = (const bulk_item & RHs) {If (this! = & RHs) item_base: Operator = (RHs); quantity = RHS. quantity; Discount = RHS. discount; STD: cout <"value assignment operator of a derived class" <STD: Endl; return * This ;}

It should be noted that we have added the judgment on whether the Left and Right operands are equal. The operation of the base class is called only when the numbers are not equal.

In destructor, we did nothing but defined it as a virtual function. Why?

Through the previous study, we know that if a class contains pointer members, we should delete the pointer members in the class's destructor. We also know that, due to dynamic binding, we can completely point a static class pointer to an object of A derived class. If you delete the object of the dispatch class through the pointer of the base class and the base class does not have a virtual destructor, the problem may occur. For example:

Class A {public: A () {PTR = new int [10]; cout <"a constructor" <Endl;} virtual ~ A () {Delete PTR; cout <"A destructor" <Endl;} PRIVATE: int * PTR;}; Class B: Public A {public: B () {PTR = new long [10]; cout <"B constructor" <Endl ;}~ B () {Delete PTR; cout <"B destructor" <Endl;} private: Long * PTR ;}; int main () {A * A = new B (); Delete A; return 0 ;}

 

Program Execution is printed in sequence: A constructor, B constructor, and a constructor.

It can be seen that the pointer created in the B constructor is not deleted because when Delete A is executed, the static type of A is a pointer to Class, therefore, the destructor of A is called to delete the object created in the constructor. When we set the Class A constructor to a virtual function, because the virtual function is dynamically bound, the destructor of the derived class will be called. In the destructor of the derived class, call the destructor of the base class. In this way, the object can be completely deleted.

The execution sequence of the next constructor and destructor must be emphasized here: When a derived class is created, the constructor of the derived class is called and then (displayed or implicitly) in this constructor) call the base class constructor, and then initialize other parts of the derived class. The Destructor first calls the derived class constructor and first analyzes the members of the derived class, finally, the destructor of the base class is implicitly called in this destructor.

The last part is a summary of the content of this section and a supplement to the previous summary:

The above section does not provide instructions for relevant content. The following describes the specific instructions through the test procedure:

First, three functions are defined:

void func1(Item_base obj){}void func2(Item_base& obj){}Item_base func3(){Item_base obj;return obj;}

These three functions seem to have not done any substantive work, but they are very representative of the new: the first two accept the reference of the base class object and the base class object respectively, the third return value is the base class object. Let's look at the main program:

Int main () {item_base iobj; // call the base class constructor and release func1 (iobj) when the function ends; // call the base class constructor to create a temporary object, the entire function releases func2 (iobj); // when reference is used, the object iobj = func3 () is not created (); // when a new item_base object is created, the base class constructor is called. // when the function returns, the copy constructor is called. // then, the base class constructor is called to cancel a local object. // then, the base class assignment is called. operator // release item_base * P = new item_base when the entire function ends; // call the base class constructor to create the item_base object Delete P; // call the Destructor bulk_item bobj When deleting the pointer; // because the constructor executes the list first, then execute the function body // print and execute the base class constructor first, and then print and construct the derived class func1 (bobj); // Since the form parameter of the func1 function is the base class, therefore, the derived class is implicitly converted into a base class Object // then the base class replication constructor is called to pass the real parameter to the form parameter // The base class destructor is called to cancel the object func2 (bobj ); // reference the creation of bulk_item * q = new bulk_item without a temporary object; // The derived class constructor calls the base class constructor Delete Q; // call the Destructor item_base OBJ (bobj); // convert the derived class to the base class, and then call the base class copy constructor return 0 ;}

The comments section of the program describes the specific functions. It is worth noting that:

1. if the function referenced by the base class is called using the real parameters of the derived class, the type conversion from the derived class to the base class does not occur, because the reference is directly bound to the derived class, and the object does not "type conversion ", only the address of the base class of the derived class is passed to the base type reference.

2. If you pass the real parameters of a derived class to a function of a base class parameter, first implicitly convert the derived class to a base class object, and then call the base class copy constructor to pass the real parameters to the form parameter.

3. When a base class is initialized with a derived class, the derived class is converted to the base class, and then the base class's copy constructor is called for processing.

 

 

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.