Reading notes effective C + + Item 38 modeled by combination (composition) for "has-a" or "is-implemented-in-terms-of"

Source: Internet
Author: User

1. What is a combination (composition)?

A combination (composition) is a relationship between types that occurs when one type of object contains an object of another type. As an example:

1 classAddress {...};//where someone lives2 3 classPhoneNumber {...};4 classPerson {5  Public:6 ...7 Private:8STD::stringName//composed Object9 Ten  OneAddress address;//ditto APhoneNumber Voicenumber;//ditto -  -PhoneNumber Faxnumber;//ditto the  -};

In this example, the person object is made up of string,address and PhoneNumber objects. For programmers, the term combination (composition) has many alternative words. Like layering (layering), containing ( containment), aggregation (aggregation), and implantation ( Embedding).

2. What does a combination of relationships mean? 2.1 Distinguishing between "is-a" and "Has-a"

The public inheritance is explained in Item 32 to mean "is-a". The combination has also another meaning. As a matter of fact, there are two meanings. a combination means " has-a ", also means" is-implemented-in-terms-of". This is because you are dealing with two different domains in the software. Some objects in your program correspond to the real things that exist in the world, if you want to model them, for example, human, vehicle, video frames and so on. Such objects are part of the application domain (Applicationdomain). Other objects are purely implementation-level artificial products. For example, cache (buffers), mutex semaphore (mutexs), search tree (searchtrees), and so on. This type of object corresponds to the implementation domain (Implementation domains) in your software. When a composition relationship occurs between objects in an application domain, it represents a "has-a" relationship. When it occurs in an implementation domain, it represents a "is-implemented-in-terms-of" relationship.

The person class above represents a "has-a" relationship. A Person object has a name, an address, and a voice and fax phone number. You can't say a person "is-a" name or a person "is-a" address. You would say a person "has-a" name and "Has-an" address. Most people can easily distinguish these, so few people confuse the meaning of "is-a" and "has-a".

2.2 Distinguishing between "is-a" and "is-implemented-in-terms-of"

More troubling is the distinction between "is-a" and "is-implemented-in-terms-of". For example, suppose you need a class template that represents a very small set of objects, that is, a collections without repeating elements. Because reuse is a good thing, your first instinct is to use the standard library's set template. When you have a template that has been implemented, why do you manually implement one?

Unfortunately, the implementation of set introduces a cost of three pointers to each of these elements. Because set is usually implemented as a balanced search tree, this guarantees that the time to search, insert, and delete is limited to the logarithmic level (logarithmic-time). This is a reasonable design when speed is more important than space, but for your application, space is more important than speed. So the set of the standard library does not provide the right tradeoff for your application. You need to implement this template yourself.

Reuse is still a good thing. As a data structure expert, you know that implementing set will have many options, one of which is to use linked lists. You also know that the standard C + + library has a list template, so you decide to reuse it.

In special cases, you decide to have your initial implementation of the set template inherit list. That is set<t> will inherit list<t>. After all, in your implementation, a set object is actually a list object. So you declare the set template as follows:

1 template<typename t>                      // the wrong-to-use list for Set23  Class public std::list<t> {...};     

It all looks good, but in fact there are some places where serious mistakes have been made. As Item32 explains, if D is a B, for B it is true for D. However, a list object may contain duplicate elements, so if the value 3051 is inserted into set<int> two times, then the list will contain two copies of 3051. Instead. A set cannot contain duplicate elements, so when 3051 is inserted into the set<int> two times, the set contains only a 3051 value. Now a set is a list that is no longer true, because some things that are true to the list object are not true for the set object.

Because the relationships between these two classes are not "is-a", public inheritance is the wrong way to model this relationship. The right way is to realize that a set object can be "Implementedin terms of" a list object:

1template<classT>//The right-to-use list for Set2 3 classSet {4 5  Public:                                            6 7 BOOLMemberConstt& Item)Const; 8 9 voidInsertConstt&item); Ten  One voidRemoveConstt&item);  A  -std::size_t size ()Const;  -  the Private:                                           -  -   -  +Std::list<t> Rep;//representation for Set data -  +};

The implementation of the set member function can depend on the functionality provided by the list and other parts of the standard library, so the implementation is straightforward, provided you are familiar with the basics of STL programming:

1Template<typename t>2 BOOLSet<t>::member (Constt& Item)Const3 {4 returnStd::find (Rep.begin (), Rep.end (), item)! =rep.end ();5 }6Template<typename t>7 voidSet<t>::insert (Constt&Item)8 {9 if(!member (item)) Rep.push_back (item);Ten } OneTemplate<typename t> A voidSet<t>::remove (Constt&Item) - { -TypeName Std::list<t>::iterator it =//See Item, for info on theStd::find (Rep.begin (), Rep.end (), item);//"TypeName" here - if(It! =rep.end ()) rep.erase (it); - } -Template<typename t> +std::size_t set<t>::size ()Const - { + returnrep.size (); A}

These functions are simple enough, they are reasonable candidates for the inline function, although I know you want to review the discussion in ITEM30 before making a decision.

Some people will argue that in order for the set interface to be better compliant with ITEM18 's recommendations, which is to design interfaces that are easy to use correctly and are not easily misused, set should follow the conventions of STL containers. But following these conventions requires a lot more work for set, which causes the relationship between list and set to be blurred. Since relationships are a key point in this article, we will sacrifice STL compatibility for better elaboration. In addition, the set interface should not overshadow the indisputable correct behavior of set: This right is the relationship between it and the list. This relationship is not "is-a" (although it initially looks like), but rather "is-implemented-in-terms-of".

3. Summary

      • The meaning of composition and public inheritance is completely different
      • In the application domain, the combination means "has-a", in the implementation domain, it means "is-implemented-in-terms-of"

Reading notes effective C + + Item 38 modeled by combination (composition) for "has-a" or "is-implemented-in-terms-of"

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.