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

Source: Internet
Author: User

Object-Oriented Programming-handle class and inheritance



Introduction:

In C ++, the irony of object-oriented programming is that objects cannot be used to support object-oriented programming. Instead, pointers or references must be used.

Void get_prices (Item_base object, Item_base * pointer, Item_base & reference) {// call cout Based on the pointer or reference type actually bound <pointer-> net_price (1) <endl; cout <reference.net _ price (1) <endl; // always calls net_price cout in the base class Item_base version <object.net _ price (1) <endl ;}

Calls made through pointer and reference are determined at runtime based on the dynamic type of the objects they are bound. However, using pointers or references will increase the burden on class users. For example, exercise 15.29 in the previous section: You need to explicitly release the dynamically applied memory.

C ++ is a general technology used to solve this problem, which is to define a packaging class orHandleClass. Handle class storage and management base class pointer. the type of the object pointed to by the pointer can be changed,It can pointBase class type objectYou can also pointDerived type object. UserAccess the inheritance level through the handle class. Because the handle class uses pointers to perform operations,Virtual Member BehaviorThe Operation will change according to the type of the object actually bound to the handle. Therefore,Handle users can obtain dynamic behaviors without worrying about pointer management..

Encapsulates the inheritance hierarchyThe handle has two important design considerations:

1) Like for any class that saves pointers, you must determineReplication ControlWhat to do. A handle that wraps an inheritance level usually looks like a smart pointer or a value.

2) The handle Class determines whether the handle interface shields or does not shield the inheritance hierarchy. If the inheritance hierarchy is not blocked, it is used to understand and use objects in the basic hierarchy.



I. pointer handle

We will define a pointer-type handle class named Sales_item to indicate the Item_base level. The Sales_item user will use it like a pointer: the user binds Sales_item to an Item_base object and uses the * and-> operators to perform Item_base operations:

// Bind a handle object to the Bulk_item object Sales_item item (Bulk_item ("0-201-82480-1", 0.20 )); // call the net_price function of the Bulk_item class item-> net_price ();


However, the Sales_item class does not need to manage the objects to which the handle points. When a user calls a function through a Sales_item object, the multi-state behavior is obtained.


1. Define the handle
The Sales_item class has three constructor functions: default constructor, copy constructor, and constructor that accepts the Item_base object. The third constructor copies the Item_base object and ensures that the Sales_item object exists as long as there is a copy. When you copy the Sales_item object or assign a value to the Sales_item object, the pointer instead of the object will be copied. Like other pointer-type handle classes, replicas are managed using counts.
So far, all the counting classes we have used use a partner class to store pointers and related usage counts. This example uses different designs ,.


The Sales_item class will have two data members, both pointer: one pointer will point to the Item_base object, and the other will point to the count. The Item_base pointer can point to an Item_base object or an object of the Item_base derived type. By pointing to the count, multiple Sales_item objects can share the same counter.
In addition to counting, the Sales_item class also defines the unreferenced operators and arrow operators:

class Sales_item{public:    Sales_item():p(0),use(new size_t(1)){}    Sales_item(const Item_base &);    Sales_item(const Sales_item &rhs):p(rhs.p),use(rhs.use)    {        ++ *use;    }    ~Sales_item()    {        decr_use();    }    Sales_item &operator=(const Sales_item &);    const Item_base *operator->() const    {        if (p)        {            return p;        }        else        {            throw std::logic_error("unbound Sales_item");        }    }    const Item_base &operator*() const    {        if (p)        {            return *p;        }        else        {            throw std::logic_error("unbound Sales_item");        }    }private:    Item_base *p;    std::size_t *use;    void decr_use()    {        if (-- *use == 0)        {            delete p;            delete use;        }    }};

2. Count replication Control

Copying the Sales_item object includes copying two pointers and adding 1 to the count. The Destructor uses the Count minus 1. If the count is reduced to 0, the pointer is revoked. Because the assignment operator needs to do the same job, it implements the destructor in a private utility called decr_use.

Value assignment operator:

Sales_item &Sales_item::operator=(const Sales_item &rhs){    ++ * rhs.use;    decr_use();    p = rhs.p;    use = rhs.use;    return *this;}

In addition to the replication control member, other functions defined by Sales_item are operator * and operator->. You can use these operators to access the Item_base member. Because the two operators return pointers and references respectively, the functions called by these operators are dynamically bound.

We only define the const versions of these operators, becauseBasicItem_baseMembers in the hierarchyAllConstMember.



3. Constructor

Out of the copy constructor, our handle has two constructor:

1) set the Item_base pointer to 0 to indicate that the handle is not associated with any object. The constructor applies for a new counter in the free storage and initializes it to 1.

2) users who want the handleCreate your own objectAnd associate the handles with these objects. The constructor will assign a new object of the appropriate type and copy the form parameter to the new object. In this way,Sales_itemClass will own the object and ensure that the lastSales_itemObjects will not be deleted before they disappear.



2. Copy unknown types

To implement the constructor that accepts the Item_base object, you must first solve the following problem:We do not knowActual object type. We do not know whether it is an Item_base object or an object of the Item_base derived type. When you do not know the exact type of an object, you often need to allocate a new copy of the book.

Tip]

A common solution to this problem is to define a virtual operation for copying. We name this operation clone.



To support the handle class, you need to add clone in each type of the inheritance hierarchy starting from the base class. The base class must define this function as a virtual function:

class Item_base{public:    virtual Item_base *clone() const    {        return new Item_base(*this);    }};

Each class must redefine this virtual function. Because the function is used to generate a new copy of the class object, the returned type is defined as the class itself:

Class Bulk_item: public Item_base {public:/** if the base class instance of the virtual function returns a reference or pointer of the class type, * The instance of the derived class of this virtual function can return the derived class of the type returned by the base class instance * (or a pointer or reference of the class type ). */Virtual Bulk_item * clone () const {return new Bulk_item (* this );}};

Define the handle Constructor

Sales_item::Sales_item(const Item_base &rhs):    p(rhs.clone()),use(new size_t(1)) {}

It calls the clone of the form parameter to generate the (virtual) copy of that object: if the real parameter is an Item_base object, the clone function of Item_base is run; if the real parameter is a Bulk_item object, the clone function of Bulk_item is executed.

// P508 exercise 15.31 class Lds_item: public Item_base {public: virtual Lds_item * clone () const {return new Lds_item (* this);} //... As before };

// Exercise 15.32/34 // (a) class Item_base {public: Item_base (const std: string & book = "", double sales_price = 0.0): isbn (book ), price (sales_price) {} virtual void debug (bool ctrl = 1, ostream & OS = cout) const {if (! Ctrl) return; OS <"ISBN: \ t" <isbn <endl <"price: \ t" <price <endl;} private: std :: string isbn; protected: double price;}; class Disc_item: public Item_base {public: Disc_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), quantity (qty), discount (disc_rate) {} virtual void debug (bool ctrl = 1, ostream & OS = cou T) const {if (! Ctrl) return; Item_base: debug (OS); OS <"quantity: \ t" <quantity <endl <"discount: \ t "<discount <endl;} protected: std: size_t quantity; // quantity of discounts that can be performed double discount; // discount rate };


// (B) class Item_base {public: Item_base (const std: string & book = "", double sales_price = 0.0, bool dbg = false): isbn (book ), price (sales_price), is_debug (dbg) {} virtual void debug (ostream & OS = cout) const {if (! Is_debug) return; OS <"ISBN: \ t" <isbn <endl <"price: \ t" <price <endl ;} void set_debug (bool dbg) {is_debug = dbg;} private: std: string isbn; protected: double price; bool is_debug;}; class Disc_item: public Item_base {public: disc_item (const std: string & book = "", double sales_price = 0.0, std: size_t qty = 0, double disc_rate = 0.0, bool dbg = false ): item_base (book, sales_price, dbg), q Uantity (qty), discount (disc_rate) {} virtual void debug (ostream & OS = cout) const {if (! Is_debug) return; Item_base: debug (OS); OS <"quantity: \ t" <quantity <endl <"discount: \ t "<discount <endl;} protected: std: size_t quantity; // quantity of discounts that can be performed double discount; // discount rate}; class Bulk_item: public Disc_item {public: Bulk_item (const std: string & book = "", double sales_price = 0.0, std: size_t qty = 0, double disc_rate = 0.0, bool dbg = false): Disc_item (book, sales_price, qty, disc_rate, dbg) {}}; class Lds_item: public Disc_item {public: Lds_item (const std :: string & book = "", double sales_price = 0.0, std: size_t qty = 0, double disc_rate = 0.0, bool dbg = false): Disc_item (book, sales_price, qty, disc_rate, dbg ){}};

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.