Google
 

Thursday, February 10, 2011

C++ Primer, Fourth Edition:Notes Chapter 13. Copy Control

  • Each type, whether a built-in or class type, defines the meaning of a (possibly empty) set of operations on objects of that type
  • Each type also defines what happens when objects of the type are created. Initialization of objects of class type is defined by constructors. Types also control what happens when objects of the type are copied, assigned, or destroyed. Classes control these actions through special member functions: the copy constructor, the assignment operator, and the destructor. This chapter covers these operations
  • When we define a new type, we specifyexplicitly or implicitlywhat happens when objects of that type are copied, assigned, and destroyed. We do so by defining special members: the copy constructor, the assignment operator, and the destructor. If we do not explicitly define the copy constructor or the assignment operator, the compiler will (usually) define them for us
  • The copy constructor is a special constructor that has a single parameter that is a (usually const) reference to the class type. The copy constructor is used explicitly when we define a new object and initialize it from an object of the same type. It is used implicitly when we pass or return objects of that type to or from functions
  • The destructor is complementary to the constructors: It is applied automatically when an object goes out of scope or when a dynamically allocated object is deleted. The destructor is used to free resources acquired when the object was constructed or during the lifetime of the object. Regardless of whether a class defines its own destructor, the compiler automatically executes the destructors for the nonstatic data members of the class
  • Like constructors, the assignment operator may be overloaded by specifying different types for the right-hand operand. The version whose right-hand operand is of the class type is special: If we do not write one, the compiler will synthesize one for us
  • Collectively, the copy constructor, assignment operator, and destructor are referred to as copy control. The compiler automatically implements these operations, but the class may define its own versions
  • Copy control is an essential part of defining any C++ class. Programmers new to C++ are often confused by having to define what happens when objects are copied, assigned, or destroyed. This confusion is compounded because if we do not explicitly define these operations, the compiler defines them for usalthough they might not behave as we intend
  • Often the compiler-synthesized copy-control functions are finethey do exactly the work that needs to be done. But for some classes, relying on the default definitions leads to disaster. Frequently, the most difficult part of implementing the copy-control operations is recognizing when we need to override the default versions. One especially common case that requires the class to define its own the copy-control members is if the class has a pointer member

Section 13.1 The Copy Constructor

  • The constructor that takes a single parameter that is a (usually const) reference to an object of the class type itself is called the copy constructor. Like the default constructor, the copy constructor can be implicitly invoked by the compiler. The copy constructor is used to
    • Explicitly or implicitly initialize one object from another of the same type
    • Copy an object to pass it as an argument to a function
    • Copy an object to return it from a function
    • Initialize the elements in a sequential container
    • Initialize elements in an array from a list of element initializers
  • Forms of Object Definition
    • Recall that C++ supports two forms of initialization (Section 2.3.3, p. 48): direct and copy. Copy-initialization uses the = symbol, and direct-initialization places the initializer in parentheses
    • The copy and direct forms of initialization, when applied to objects of class type, are subtly different. Direct-initialization directly invokes the constructor matched by the arguments. Copy-initialization always involves the copy constructor. Copy-initialization first uses the indicated constructor to create a temporary object (Section 7.3.2, p. 247). It then uses the copy constructor to copy that temporary into the one we are creating
    • For objects of class type, copy-initialization can be used only when specifying a single argument or when we explicitly build a temporary object to copy
    • The copy form of initialization is primarily supported for compatibility with C usage. When it can do so, the compiler is permitted (but not obligated) to skip the copy constructor and create the object directly
    • Usually the difference between direct- or copy-initialization is at most a matter of low-level optimization. However, for types that do not support copying, or when using a constructor that is nonexplicit (Section 12.4.4, p. 462) the distinction can be essential
  • Parameters and Return Values
    • As we know, when a parameter is a nonreference type (Section 7.2.1, p. 230), the argument is copied. Similarly, a nonreference return value (Section 7.3.2, p. 247) is returned by copying the value in the return statement
    • When the parameter or return type is a class type, the copy is done by the copy constructor
  • Initializing Container Elements
    • The copy constructor is used to initialize the elements in a sequential container
    • As a general rule (Section 9.1.1, p. 307), unless you intend to use the default initial value of the container elements, it is more efficient to allocate an empty container and add elements as the values for those elements become known
  • Constructors and Array Elements
    • If we provide no element initializers for an array of class type, then the default constructor is used to initialize each element. However, if we provide explicit element initializers using the normal brace-enclosed array initialization list (Section 4.1.1, p. 111), then each element is initialized using copy-initialization. An element of the appropriate type is created from the specified value, and then the copy constructor is used to copy that value to the corresponding element
  • 13.1.1. The Synthesized Copy Constructor
    • If we do not otherwise define the copy constructor, the compiler synthesizes one for us. Unlike the synthesized default constructor (Section 12.4.3, p. 458), a copy constructor is synthesized even if we define other constructors. The behavior of the synthesized copy constructor is to memberwise initialize the new object as a copy of the original object
    • By memberwise, we mean that taking each nonstatic member in turn, the compiler copies the member from the existing object into the one being created. With one exception, the type of each member determines what it means to copy it. The synthesized copy constructor directly copies the value of members of built-in type. Members of class type are copied by using the copy constructor for that class. The one exception concerns array members. Even though we ordinarily cannot copy an array, if a class has a member that is an array, then the synthesized copy constructor will copy the array. It does so by copying each element
    • The simplest conceptual model of memberwise initialization is to think of the synthesized copy constructor as one in which each data member is initialized in the constructor initializer list
  • 13.1.2. Defining Our Own Copy Constructor
    • The copy constructor is the constructor that takes a single parameter that is a (usually const) reference to the class type
      class Foo {
           public:
              Foo();           // default constructor
              Foo(const Foo&); // copy constructor
              // ...
           };

    • Usually the parameter is a const reference, although we can also define the copy constructor to take a nonconst reference. Because the constructor is used (implicitly) to pass and return objects to and from functions, it usually should not be made explicit (Section 12.4.4, p. 462). The copy constructor should copy the members from its argument into the object that is being constructed
    • For many classes, the synthesized copy constructor does exactly the work that is needed. Classes that contain only members that are of class type or members that are of built-in (but not pointer type) often can be copied without explicitly defining the copy constructor
    • However, some classes must take control of what happens when objects are copied. Such classes often have a data member that is a pointer or that represents another resource that is allocated in the constructor. Other classes have bookkeeping that must be done whenever a new object is created. In both these cases, the copy constructor must be defined
    • Often the hardest part about defining a copy constructor is recognizing that a copy constructor is needed. Defining the constructor is usually pretty easy once the need for the constructor is recognized. The copy constructor itself is defined like any other constructor: It has the same name as the name of the class, it has no return value, it may (should) use a constructor initializer to initialize the members of the newly created object, and it may do any other necessary work inside a function body

  • 13.1.3. Preventing Copies

    • Some classes need to prevent copies from being made at all
    • To prevent copies, a class must explicitly declare its copy constructor as private
    • If the copy constructor is private, then user code will not be allowed to copy objects of the class type. The compiler will reject any attempt to make a copy
    • However, the friends and members of the class could still make copies. If we want to prevent copies even within the friends and members, we can do so by declaring a (private) copy constructor but not defining it
    • Most Classes Should Define Copy and Default Constructors

      • Classes that do not define the default constructor and/or the copy constructor impose serious limits on users of the class. Objects of classes that do not allow copies may be passed to (or returned from) a function only as a reference. They also may not be used as elements in a container
      • It is usually best to defineeither implicitly or explicitlythe default and copy constructors. The default constructor is synthesized only if there are no other constructors. If the copy constructor is defined, then the default constructor must be defined as well


Section 13.2 The Assignment Operator



  • Just as classes control how objects are initialized, they also define what happens when objects of their type are assigned
  • As with the copy constructor, the compiler synthesizes an assignment operator if the class does not define its own
  • Introducing Overloaded Assignment

    • Overloaded operators are functions that have the name operator followed by the symbol for the operator being defined. Hence, we define assignment by defining a function named operator=. Like any other function, an operator function has a return type and a parameter list. The parameter list must have the same number of parameters (including the implicit this parameter if the operator is a member) as the operator has operands. Assignment is binary, so the operator function has two parameters: The first parameter corresponds to the left-hand operand, and the second to the right-hand operand
    • Most operators may be defined as member or nonmember functions. When an operator is a member function, its first operand is implicitly bound to the this pointer. Some operators, assignment among them, must be members of the class for which the operator is defined. Because assignment must be a member of its class, this is bound to a pointer to the left-hand operand. The assignment operator, therefore, takes a single parameter that is an object of the same class type. Usually, the right-hand operand is passed as a const reference
    • The return type from the assignment operator should be the same as the return from assignment for the built-in types (Section 5.4.1, p. 160). Assignment to a built-in type returns a reference to its left-hand operand. Therefore, the assignment operator also returns a reference to the same type as its class

  • The Synthesized Assignment Operator

    • The synthesized assignment operator operates similarly to the synthesized copy constructor. It performs memberwise assignment: Each member of the right-hand object is assigned to the corresponding member of the left-hand object. Except for arrays, each member is assigned in the usual way for its type. For arrays, each array element is assigned
    • The synthesized assignment operator assigns each member in turn, using the built-in or class-defined assignment operator as appropriate to the type of the member. The operator returns *this, which is a reference to the left-hand object

  • Copy and Assign Usually Go Together

    • Classes that can use the synthesized copy constructor usually can use the synthesized assignment operator as well
    • However, a class may define its own assignment operator. In general, if a class needs a copy constructor, it will also need an assignment operator
    • In fact, these operations should be thought of as a unit. If we require one, we almost surely require the other


Section 13.3 The Destructor



  • The destructor is a special member function that can be used to do whatever resource deallocation is needed. It serves as the complement to the constructors of the class
  • When a Destructor Is Called

    • The destructor is called automatically whenever an object of its class is destroyed
    • An object that is dynamically allocated is destroyed only when a pointer pointing to the object is delete d. If we do not delete a pointer to a dynamically allocated object, then the destructor is never run on that object. The object will persist forever, leading to a memory leak. Moreover, any resources used inside the object will also not be released
    • The destructor is not run when a reference or a pointer to an object goes out of scope. The destructor is run only when a pointer to a dynamically allocated object is deleted or when an actual object (not a reference to the object) goes out of scope
    • Destructors are also run on the elements of class type in a container whether a library container or built-in array when the container is destroyed
    • The elements in the container are always destroyed in reverse order: The element indexed by size() - 1 is destroyed first, followed by the one indexed by size() - 2 and so on until element [0], which is destroyed last

  • When to Write an Explicit Destructor

    • Many classes do not require an explicit destructor. In particular, a class that has a constructor does not necessarily need to define its own destructor. Destructors are needed only if there is work for them to do. Ordinarily they are used to relinquish resources acquired in the constructor or during the lifetime of the object
    • A useful rule of thumb is that if a class needs a destructor, it will also need the assignment operator and a copy constructor. This rule is often referred to as the Rule of Three, indicating that if you need a destructor, then you need all three copy-control members
    • A destructor is not limited only to relinquishing resources. A destructor, in general, can perform any operation that the class designer wishes to have executed subsequent to the last use of an object of that class

  • The Synthesized Destructor

    • Unlike the copy constructor or assignment operator, the compiler always synthesizes a destructor for us. The synthesized destructor destroys each nonstatic member in the reverse order from that in which the object was created. In consequence, it destroys the members in reverse order from which they are declared in the class. For each member that is of class type, the synthesized destructor invokes that member's destructor to destroy the object
    • Destroying a member of built-in or compound type has no effect. In particular, the synthesized destructor does not delete the object pointed to by a pointer member

  • How to Write a Destructor

    • Classes that do allocate resources usually need to define a destructor to free those resources. The destructor is a member function with the name of the class prefixed by a tilde (~). It has no return value and takes no parameters. Because it cannot specify any parameters, it cannot be overloaded. Although we can define multiple class constructors, we can provide only a single destructor to be applied to all objects of our class
    • An important difference between the destructor and the copy constructor or assignment operator is that even if we write our own destructor, the synthesized destructor is still run


Section 13.4 A Message-Handling Example



  • The Message Class

  • Copy Control for the Message Class


    • When we write our own copy constructor, we must explicitly copy any members that we want copied. An explicitly defined copy constructor copies nothing automatically

    • As with any other constructor, if we do not initialize a class member, then that member is initialized using the member's default constructor. Default initialization in a copy constructor does not use the member's copy constructor

  • The put_Msg_in_Folders Member

  • Message Assignment Operator


    • The assignment operator starts by checking that the left- and right-hand operands are not the same. We do this check for reasons that will become apparent as we walk through the rest of the function

    • Assignment involves obliterating the left-hand operand. Once the members of the left-hand operand are destroyed, those in the right-hand operand are assigned to the corresponding left-hand members. If the objects were the same, then destroying the left-hand members would also destroy the right-hand members

    • It is crucially important for assignment operators to work correctly, even when an object is assigned to iself. A common way to ensure this behavior is by checking explicitly for self-assignment

  • The remove_Msg_from_Folders Member

  • The Message Destructor


    • The assignment operator often does the same work as is needed in the copy constructor and destructor. In such cases, the common work should be put in private utility functions


Section 13.5 Managing Pointer Members



  • Classes that contain pointers require careful attention to copy control. The reason they must do so is that copying a pointer copies only the address in the pointer. Copying a pointer does not copy the object to which the pointer points.

  • When designing a class with a pointer member, the first decision a class author must make is what behavior that pointer should provide. When we copy one pointer to another, the two pointers point to the same object. When two pointers point to the same object, it is possible to use either pointer to change the underlying object. Similarly, it is possible for one pointer to delete the object even though the user of the other pointer still thinks the underlying object exists

  • By default, a pointer member has the same behavior as a pointer object. However, through different copy-control strategies we can implement different behavior for pointer members

  • Most C++ classes take one of three approaches to managing pointer members


    • The pointer member can be given normal pointer like behavior. Such classes will have all the pitfalls of pointers but will require no special copy control.

    • The class can implement so-called "smart pointer" behavior. The object to which the pointer points is shared, but the class prevents dangling pointers.

    • The class can be given value like behavior. The object to which the pointer points will be unique to and managed separately by each class object.

  • In this section we look at three classes that implement each of these different approaches to managing their pointer members.

  • A Simple Class with a Pointer Member

  • Default Copy/Assignment and Pointer Members


    • Classes that have pointer members and use default synthesized copy control have all the pitfalls of ordinary pointers. In particular, the class itself has no way to avoid dangling pointers

  • Pointers Share the Same Object

  • Dangling Pointers Are Possible

  • 13.5.1. Defining Smart Pointer Classes


    • An alternative to having a pointer member behave exactly like a pointer is to define what is sometimes referred to as a smart pointer class. A smart pointer behaves like an ordinary pointer except that it adds functionality.

    • In this case, we'll give our smart pointer the responsibility for deleting the shared object. Users will dynamically allocate an object and pass the address of that object to our new HasPtr class. The user may still access the object through a plain pointer but must not delete the pointer. The HasPtr class will ensure that the object is deleted when the last HasPtr that points to it is destroyed.

    • Our new HasPtr class will need a destructor to delete the pointer. However, the destructor cannot delete the pointer unconditionally. If two HasPtr objects point to the same underlying object, we don't want to delete the object until both objects are destroyed. To write the destructor, we need to know whether this HasPtr is the last one pointing to a given object

    • Introducing Use Counts


      • A common technique used in defining smart pointers is to use a use count. The pointerlike class associates a counter with the object to which the class points. The use count keeps track of how many objects of the class share the same pointer. When the use count goes to zero, then the object is deleted. A use count is sometimes also referred to as a reference count

      • Each time a new object of the class is created, the pointer is initialized and the use count is set to 1. When an object is created as a copy of another, the copy constructor copies the pointer and increments the associated use count. When an object is assigned to, the assignment operator decrements the use count of the object to which the left-hand operand points (and deletes that object if the use count goes to zero) and increments the use count of the object pointed to by the right-hand operand. Finally, when the destructor is called, it decrements the use count and deletes the underlying object if the count goes to zero

    • The Use-Count Class


      • There are two classic strategies for implementing a use count, one of which we will use here; the other approach is described in Section 15.8.1 (p. 599). In the approach we use here, we'll define a separate concrete class to encapsulate the use count and the associated pointer

    • Using the Use-Counted Class

    • Assignment and Use Counts


      • This assignment operator guards against self-assignment by incrementing the use count of rhs before decrementing the use count of the left-hand operand

    • Changing Other Members

    • Advice: Managing Pointer Members


      Objects with pointer members often need to define the copy-control members. If we rely on the synthesized versions, then the class puts a burden on its users. Users must ensure that the object to which the member points stays around for at least as long as the object that points to it does.


      To manage a class with pointer members, we must define all three copy-control members: the copy constructor, assignment operator, and the destructor. These members can define either pointerlike or valuelike behavior for the pointer member.


      Valuelike classes give each object its own copy of the underlying values pointed to by pointer members. The copy constructor allocates a new element and copies the value from the object it is copying. The assignment operator destroys the existing object it holds and copies the value from its right-hand operand into its left-hand operand. The destructor destroys the object.


      As an alternative to defining either valuelike behavior or pointerlike behavior some classes are so-called "smart pointers." These classes share the same underlying value between objects, thus providing pointerlike behavior. But they use copy-control techniques to avoid some of the pitfalls of regular pointers. To implement smart pointer behavior, a class needs to ensure that the underlying object stays around until the last copy goes away. Use counting (Section 13.5.1, p. 495), is a common technique for managing smart pointer classes. Each copy of the same underlying value is given a use count. The copy constructor copies the pointer from the old object into the new one and increments the use count. The assignment operator decrements the use count of the left-hand operand and increments the count of the right-hand operand. If the use count of the left-hand operand goes to zero, the assignment operator must delete the object to which it points. Finally, the assignment operator copies the pointer from the right-hand operand into its left-hand operand. The destructor decrements the use count and deletes the underlying object if the count goes to zero.









      These approaches to managing pointers occur so frequently that programmers who use classes with pointer members must be thoroughly familiar with these programming techniques.


  • 13.5.2. Defining Value like Classes


    • A completely different approach to the problem of managing pointer members is to give them value semantics. Simply put, classes with value semantics define objects that behave like the arithmetic types: When we copy a valuelike object, we get a new, distinct copy. Changes made to the copy are not reflected in the original, and vice versa. The string class is an example of a valuelike class

    • The copy constructor no longer copies the pointer. It now allocates a new int object and initializes that object to hold the same value as the object of which it is a copy. Each object always holds its own, distinct copy of its int value. Because each object holds its own copy, the destructor unconditionally deletes the pointer

    • As always, the assignment operator must be correct even if we're assigning an object to itself. In this case, the operations are inherently safe even if the left- and right-hand objects are the same. Thus, there is no need to explicitly check for self-assignment

Wednesday, February 9, 2011

C++ Primer, Fourth Edition:Notes Chapter 11. Generic Algorithms

Section 11.1 Overview

 

Section 11.2 A First Look at the Algorithms

Section 11.3 Revisiting Iterators

Section 11.4 Structure of Generic Algorithms

Section 11.5 Container-Specific Algorithms

Good windows live writer code format plugin

 

Please download it here:http://wlwplugincollection.codeplex.com/releases/view/9392

C++ Primer, Fourth Edition:Notes Chapter 12. Classes

Section 12.1 Class Definitions and Declarations

In C++ we use classes to define our own abstract data types. By defining types that mirror concepts in the problems we are trying to solve, we can make our programs easier to write, debug, and modify

Classes are the most important feature in C++. Early versions of the language were named "C with Classes," emphasizing the central role of the class facility. As the language evolved, support for building classes increased. A primary goal of the language design has been to provide features that allow programmers to define their own types that are as easy and intuitive to use as the built-in types. This chapter presents many of the basic features of classes

 

  • 12.1.1. Class Definitions: A Recap
    • Most fundamentally, a class defines a new type and a new scope
    • Class Members
      • Each class defines zero or more members. Members can be either data, functions, or type definitions
      • A class may contain multiple public, private, and protected sections
      • All members must be declared inside the class; there is no way to add members once the class definition is complete
    • Constructors
      • When we create an object of a class type, the compiler automatically uses a constructor (Section 2.3.3, p. 49) to initialize the object. A constructor is a special member function that has the same name as the class. Its purpose is to ensure that each data member is set to sensible initial values
      • A constructor generally should use a constructor initializer list (Section 7.7.3, p. 263), to initialize the data members of the object
      • The constructor initializer list is a list of member names and parenthesized initial values. It follows the constructor's parameter list and begins with a colon
    • Member Functions
      • Member functions must be declared, and optionally may be defined, inside the class; functions defined inside the class are inline (Section 7.6, p. 256) by default
      • Member functions defined outside the class must indicate that they are in the scope of the class. The definition of Sales_item::avg_price uses the scope operator (Section 1.2.2, p. 8) to indicate that the definition is for the avg_price function of the Sales_item class
      • Member functions take an extra implicit argument that binds the function to the object on behalf of which the function is calledwhen we write trans.avg_price() we are calling the avg_price function on the object named trans. If TRans is a Sales_item object, then references to a member of the Sales_item class inside the avg_price function are to the members in trans.
      • A const member may not change the data members of the object on which it operates. The const must appear in both the declaration and definition. It is a compile-time error for the const to be indicated on one but not the other
  • 12.1.2. Data Abstraction and Encapsulation
    • The fundamental ideas behind classes are data abstraction and encapsulation
    • Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation. The class designer must worry about how a class is implemented, but programmers that use the class need not know about these details. Instead, programmers who use a type need to know only the type's interface; they can think abstractly about what the type does rather than concretely about how the type works
    • Encapsulation is a term that describes the technique of combining lower-level elements to form a new, higher-level entity. A function is one form of encapsulation: The detailed actions performed by the function are encapsulated in the larger entity that is the function itself. Encapsulated elements hide the details of their implementationwe may call a function but have no access to the statements that it executes. In the same way, a class is an encapsulated entity: It represents an aggregation of several members, and most (well-designed) class types hide the members that implement the type
    • Access Labels Enforce Abstraction and Encapsulation
      • Members defined after a public label are accessible to all parts of the program. The data-abstraction view of a type is defined by its public members
      • Members defined after a private label are not accessible to code that uses the class. The private sections encapsulate (e.g., hide) the implementation from code that uses the type
      • There are no restrictions on how often an access label may appear. Each access label specifies the access level of the succeeding member definitions. The specified access level remains in effect until the next access label is encountered or the closing right brace of the class body is seen
      • A class may define members before any access label is seen. The access level of members defined after the open curly of the class and before the first access label depend on how the class is defined. If the class is defined with the struct keyword, then members defined before the first access label are public; if the class is defined using the class keyword, then the members are private

    Advice: Concrete and Abstract Types

    Not all types need to be abstract. The library pair class is a good example of a useful, well-designed class that is concrete rather than abstract. A concrete class is a class that exposes, rather than hides, its implementation.

    Some classes, such as pair, really have no abstract interface. The pair type exists to bundle two data members into a single object. There is no need or advantage to hiding the data members. Hiding the members in a class like pair would only complicate the use of the type.

    Even so, such types often have member functions. In particular, it is a good idea for any class that has data members of built-in or compound type to define constructor(s) to initialize those members. The user of the class could initialize or assign to the data members but it is less error-prone for the class to do so.


      • Different Kinds of Programming Roles
        • When designing the interface to a class, the class designer should think about how easy it will be to use the class. When using the class, the designer shouldn't think about how the class works
        • C++ programmers tend to speak of "users" interchangably as users of the application or users of a class
        • Key Concept: Benefits of Data Abstraction and Encapsulation

          Data abstraction and encapsulation provide two important advantages:

          • Class internals are protected from inadvertent user-level errors, which might corrupt the state of the object.

          • The class implementation may evolve over time in response to changing requirements or bug reports without requiring change in user-level code.

          By defining data members only in the private section of the class, the class author is free to make changes in the data. If the implementation changes, only the class code needs to be examined to see what affect the change may have. If data are public, then any function that directly accesses the data members of the old representation might be broken. It would be necessary to locate and rewrite all those portions of code that relied on the old representation before the program could be used again.

          Similarly, if the internal state of the class is private, then changes to the member data can happen in only a limited number of places. The data is protected from mistakes that users might introduce. If there is a bug that corrupts the object's state, the places to look for the bug are localized: When data are private, only a member function could be responsible for the error. The search for the mistake is limited, greatly easing the problems of maintenance and program correctness.

          If the data are private and if the interface to the member functions does not change, then user functions that manipulate class objects require no change.

          Because changing a class definition in a header file effectively changes the text of every source file that includes that header, code that uses a class must be recompiled when the class changes.




    • 12.1.3. More on Class Definitions
      • Multiple Data Members of the Same Type
        • One way in which member declarations and ordinary declarations are the same is that if a class has multiple data members with the same type, these members can be named in a single member declaration
      • Using Typedefs to Streamline Classes
        • In addition to defining data and function members, a class can also define its own local names for types
        • Type names defined by a class obey the standard access controls of any other member. We put the definition of index in the public part of the class because we want users to use that name
      • Member Functions May Be Overloaded
        • With the exception of overloaded operators (Section 14.9.5, p. 547)which have special rulesa member function overloads only other member functions of its own class. A class member function is unrelated to, and cannot overload, ordinary nonmember functions or functions declared in other classes. The same rules apply to overloaded member functions as apply to plain functions: Two overloaded members cannot have the same number and types of parameters
      • Defining Overloaded Member Functions
      • Explicitly Specifying inline Member Functions
        • We can specify that a member is inline as part of its declaration inside the class body. Alternatively, we can specify inline on the function definition that appears outside the class body. It is legal to specify inline both on the declaration and definition. One advantage of defining inline functions outside the class is that it can make the class easier to read
        • As with other inlines, the definition of an inline member function must be visible in every source file that calls the function. The definition for an inline member function that is not defined within the class body ordinarily should be placed in the same header file in which the class definition appears
    • 12.1.4. Class Declarations versus Definitions
      • A class is completely defined once the closing curly brace appears. Once the class is defined, all the class members are known
      • The size required to store an object of the class is known as well
      • A class may be defined only once in a given source file. When a class is defined in multiple files, the definition in each file must be identical.
      • By putting class definitions in header files, we can ensure that a class is defined the same way in each file that uses it. By using header guards (Section 2.9.2, p. 69), we ensure that even if the header is included more than once in the same file, the class definition will be seen only once
      • It is possible to declare a class without defining it
      • This declaration, sometimes referred to as a forward declaration, introduces the name Screen into the program and indicates that Screen refers to a class type. After a declaration and before a definition is seen, the type Screen is an incompete typeit's known that Screen is a type but not known what members that type contains
      • An incomplete type can be used only in limited ways. Objects of the type may not be defined. An incomplete type may be used to define only pointers or references to the type or to declare (but not define) functions that use the type as a paremeter or return type
      • A data member can be specified to be of a class type only if the definition for the class has already been seen. If the type is incomplete, a data member can be only a pointer or a reference to that class type
      • However, a class is considered declared as soon as its class name has been seen. Therefore, a class can have data members that are pointers or references to its own type
      • A common use of class forward declarations is to write classes that are mutually dependent on one another
    • 12.1.5. Class Objects
      • When we define a class, we are defining a type. Once a class is defined, we can define objects of that type. Storage is allocated when we define objects, but (ordinarily) not when we define types
      • Each object has its own copy of the class data members. Modifying the data members of item does not change the data members of any other Sales_item object
      • Defining Objects of Class Type
        • Using the class name directly as a type name
      • Why a Class Definition Ends in a Semicolon
        • A semicolon is required because we can follow a class definition by a list of object definitions. As always, a definition must end in a semicolon
        • Ordinarily, it is a bad idea to define an object as part of a class definition. Doing so obscures what's happening. It is confusing to readers to combine definitions of two different entitiesthe class and a variablein a single statement

    Section 12.2 The Implicit this Pointer

    • member functions have an extra implicit parameter that is a pointer to an object of the class type. This implicit parameter is named this, and is bound to the object on which the member function is called
    • Member functions may not define the this parameter; the compiler does so implicitly. The body of a member function may explicitly use the this pointer, but is not required to do so. The compiler treats an unqualified reference to a class member as if it had been made through the this pointer
    • When to Use the this Pointer
      • there is one case in which we must do so: when we need to refer to the object as a whole rather than to a member of the object
    • Returning *this
    • Returning *this from a const Member Function
      • In an ordinary nonconst member function, the type of this is a const pointer (Section 4.2.5, p. 126) to the class type. We may change the value to which this points but cannot change the address that this holds
      • In a const member function, the type of this is a const pointer to a const class-type object. We may change neither the object to which this points nor the address that this holds
      • We cannot return a plain reference to the class object from a const member function. A const member function may return *this only as a const reference
    • Overloading Based on const
      • We can overload a member function based on whether it is const for the same reasons that we can overload a function based on whether a pointer parameter points to const
      • A const object will use only the const member. A nonconst object could use either member, but the nonconst version is a better match
    • Mutable Data Members
      • It sometimes (but not very often) happens that a class has a data member that we want to be able to modify, even inside a const member function. We can indicate such members by declaring them as mutable
      • A mutable data member is a member that is never const, even when it is a member of a const object. Accordingly, a const member function may change a mutable member

        Advice: Use Private Utility Functions for Common Code

        Some readers might be surprised that we bothered to define a separate do_display operation. After all, the calls to do_display aren't much simpler than the action done inside do_display. Why bother? We do so for several reasons:

        1. A general desire to avoid writing the same code in more than one place.

        2. The display operation can be expected to become more complicated as our class evolves. As the actions involved become more complex, it makes more obvious sense to write those actions in one place, not two.

        3. It is likely that we might want to add debugging information to do_display during development that would be eliminated in the final product version of the code. It will be easier to do so if only one definition of do_display needs to be changed to add or remove the debugging code.

        4. There needn't be any overhead involved in this extra function call. We made do_display inline, so the run-time performance between calling do_display or putting the code directly into the display operations should be identical.

        In practice, well-designed C++ programs tend to have lots of small functions such as do_display that are called to do the "real" work of some other set of functions.


      • a

    Section 12.3 Class Scope

    1. Every class defines its own new scope and a unique type. The declarations of the class members within the class body introduce the member names into the scope of their class. Two different classes have two different class scopes
    2. Even if two classes have exactly the same member list, they are different types. The members of each class are distinct from the members of any other class (or any other scope).
    3. Using a Class Member
      1. Outside the class scope, members may be accessed only through an object or a pointer using member access operators dot or arrow, respectively
      2. Some members are accessed using the member access operators; others are accessed directly from the class using the scope operator, (::). Ordinary data or function members must be accessed through an object. Members that define types, such as Screen::index, are accessed using the scope operator
    4. Scope and Member Definitions
      1. Member definitions behave as if they are in the scope of the class, even if the member is defined outside the class body
    5. Parameter Lists and Function Bodies Are in Class Scope
      1. These are defined inside the class scope and so may refer to other class members without qualification
    6. Function Return Types Aren't Always in Class Scope
      1. If the function is defined outside the class body, then the name used for the return type is outside the class scope. If the return type uses a type defined by the class, it must use the fully qualified name
    7. 12.3.1. Name Lookup in Class Scope
      1. In the programs we've written so far, name lookup (the process of finding which declaration is matched to a given use of a name) has been relatively straightforward
        1. First, look for a declaration of the name in the block in which the name was used. Only names declared before the use are considered.
        2. If the name isn't found, the enclosing scope(s) are searched.
      2. If no declaration is found, then the program is in error. In C++ programs, all names must be declared before they are used
      3. Class scopes may seem to behave a bit differently, but in reality they obey this same rule. Confusion can arise due to the way names are resolved inside a function defined within the class body itself
      4. Class definitions are actually processed in two phases
        1. First, the member declarations are compiled
        2. Only after all the class members have been seen are the definitions themselves compiled
      5. Of course, the names used in class scope do not always have to be class member names. Name lookup in class scope finds names declared in other scopes as well. During name lookup, if a name used in class scope does not resolve to a class member name, the scopes surrounding the class or member definition are searched to find a declaration for the name
      6. Name Lookup for Class Member Declarations
        1. Names used in the declarations of a class member are resolved as follows
          1. The declarations of the class members that appear before the use of the name are considered
          2. If the lookup in step 1 is not successful, the declarations that appear in the scope in which the class is defined, and that appear before the class definition itself, are considered
        2. Names of types defined in a class must be seen before they are used as the type of a data member or as the return type or parameter type(s) of a member function
        3. The compiler handles member declarations in the order in which they appear in the class. As usual, a name must be defined before it can be used. Moreover, once a name has been used as the name of a type, that name may not be redefined
      7. Name Lookup in Class Member Definitions
        1. A name used in the body of a member function is resolved as follows
          1. Declarations in the member-function local scopes are considered first
          2. If the a declaration for the name is not found in the member function, the declarations for all the class members are considered
          3. If a declaration for the name is not found in the class, the declarations that appear in scope before the member function definition are considered
      8. Class Members Follow Normal Block-Scope Name Lookup
        1. Programs that illustrate how name lookup works often have to rely on bad practices. The next several programs contain bad style deliberately
        2. The following function uses the same name for a parameter and a member, which normally should be avoided
        3. Even though the class member is hidden, it is still possible to use it by qualifying the member's name with the name of its class or by using the this pointer explicitly
      9. After Function Scope, Look in Class Scope
      10. After Class Scope, Look in the Surrounding Scope
        1. Even though the global object is hidden, it is still possible to use it by qualifying the name with the global scope resolution operator
      11. Names Are Resolved Where They Appear within the File
        1. When a member is defined outside the class definition, the third step of name lookup not only considers the declarations in global scope that appear before the definition of class Screen, but also considers the global scope declarations that appear before the member function definition

    Section 12.4 Constructors

    1. Constructors (Section 2.3.3, p. 49) are special member functions that are executed whenever we create new objects of a class type. The job of a constructor is to ensure that the data members of each object start out with sensible initial values
    2. Constructors have the same name as the name of the class and may not specify a return type. Like any other function, they may define zero or more parameters
    3. Constructors May Be Overloaded
      1. There is no constraint on the number of constructors we may declare for a class, provided that the parameter list of each constructor is unique. How can we know which or how many constructors to define? Ordinarily, constructors differ in ways that allow the user to specify differing ways to initialize the data members
    4. Arguments Determine Which Constructor to Use
      1. The argument type(s) used to initialize an object determines which constructor is used
    5. Constructors Are Executed Automatically
      1. The compiler runs a constructor whenever an object of the type is created
    6. Constructors for const Objects
      1. A constructor may not be declared as const
      2. There is no need for a const constructor. When we create a const object of a class type, an ordinary constructor is run to initialize the const object. The job of the constructor is to initialize an object. A constructor is used to initialize an object regardless of whether the object is const
    7. 12.4.1. The Constructor Initializer
      1. Like any other function, a constructor has a name, a parameter list, and a function body. Unlike other functions, a constructor may also contain a constructor initializer list
      2. The constructor initializer starts with a colon, which is followed by a comma-separated list of data members each of which is followed by an initializer inside parentheses
      3. As with any member function, constructors can be defined inside or outside of the class. The constructor initializer is specified only on the constructor definition, not its declaration
      4. The constructor initializer is a feature that many reasonably experienced C++ programmers have not mastered
      5. Data members of class type are always initialized in the initialization phase, regardless of whether the member is initialized explicitly in the constructor initializer list. Initialization happens before the computation phase begins
      6. Each member that is not explicitly mentioned in the constructor initializer is initialized using the same rules as those used to initialize variables (Section 2.3.4, p. 50). Data members of class type are initialized by running the type's default constructor. The initial value of members of built-in or compound type depend on the scope of the object: At local scope those members are uninitialized, at global scope they are initialized to 0
      7. Constructor Initializers Are Sometimes Required
        1. If an initializer is not provided for a class member, then the compiler implicitly uses the default constructor for the member's type. If that class does not have a default constructor, then the attempt by the compiler to use it will fail. In such cases, an initializer must be provided in order to initialize the data member
        2. Some members must be initialized in the constructor initializer. For such members, assigning to them in the constructor body doesn't work. Members of a class type that do not have a default constructor and members that are const or reference types must be initialized in the constructor initializer regardless of type
        3. Remember that we can initialize but not assign to const objects or objects of reference type. By the time the body of the constructor begins executing, initialization is complete. Our only chance to initialize const or reference data members is in the constructor initializer

          Advice: Use Constructor Initializers

          In many classes, the distinction between initialization and assignment is strictly a matter of low-level efficiency: A data member is initialized and assigned when it could have been initialized directly. More important than the efficiency issue is the fact that some data members must be initialized.

          We must use an initializer for any const or reference member or for any member of a class type that does not have a default constructor.



          By routinely using constructor initializers, we can avoid being surprised by compile-time errors when we have a class with a member that requires a constructor initializer.

      8. Order of Member Initialization
        1. Not surprisingly, each member may be named only once in the constructor initializer. After all, what might it mean to give a member two initial values? What may be more surprising is that the constructor initializer list specifies only the values used to initialize the members, not the order in which those initializations are performed. The order in which members are initialized is the order in which the members are defined. The first member is initialized first, then the next, and so on
        2. The order of initialization often doesn't matter. However, if one member is initialized in terms of another, then the order in which members are initialized is crucially important
        3. It is a good idea to write constructor initializers in the same order as the members are declared. Moreover, when possible, avoid using members to initialize other members
        4. It is often the case that we can avoid any problems due to order of execution for initializers by (re)using the constructor's parameters rather than using the object's data members
      9. Initializers May Be Any Expression
        1. An initializer may be an arbitrarily complex expression
      10. Initializers for Data Members of Class Type
        1. When we initialize a member of class type, we are specifying arguments to be passed to one of the constructors of that member's type. We can use any of that type's constructors
    8. 12.4.2. Default Arguments and Constructors
      1. We can combine these constructors by supplying a default argument for the string initializer
      2. We prefer to use a default argument because it reduces code duplication.
      3. Smile 
        class Sales_item {
             public:
                 // default argument for book is the empty string
                 Sales_item(const std::string &book = ""):
                           isbn(book), units_sold(0), revenue(0.0) { }
                 Sales_item(std::istream &is);
                 // as before
             };
         
         

    9. 12.4.3. The Default Constructor

      1. The default constructor is used whenever we define an object but do not supply an initializer. A constructor that supplies default arguments for all its parameters also defines the default constructor
      2. The Synthesized Default Constructor

        1. If a class defines even one constructor, then the compiler will not generate the default constructor. The basis for this rule is that if a class requires control to initialize an object in one case, then the class is likely to require control in all cases
        2. The compiler generates a default constructor automatically only if a class defines no constructors
        3. The synthesized default constructor initializes members using the same rules as those that apply for how variables are initialized. Members that are of class type are initialized by running each member's own default constructor. Members of built-in or compound type, such as pointers and arrays, are initialized only for objects that are defined at global scope. When objects are defined at local scope, then members of built-in or compound type are uninitialized
        4. If a class contains data members of built-in or compound type, then the class should not rely on the synthesized default constructor. It should define its own constructor to initialize these members

      3. Classes Should Usually Define a Default Constructor

        1. In certain cases, the default constructor is applied implicitly by the compiler. If the class has no default constructor, then the class may not be used in these contexts
        2. In practice, it is almost always right to provide a default constructor if other constructors are being defined. Ordinarily the initial values given to the members in the default constructor should indicate that the object is "empty."

      4. Using the Default Constructor

    10. 12.4.4. Implicit Class-Type Conversions

      1. To define an implicit conversion to a class type, we need to define an appropriate constructor.
      2. Suppressing Implicit Conversions Defined by Constructors

        1. We can prevent the use of a constructor in a context that requries an implicit conversion by declaring the constructor explicit
        2. The explicit keyword is used only on the constructor declaration inside the class. It is not repeated on a definition made outside the class body
        3. When a constructor is declared explicit, the compiler will not use it as a conversion operator

      3. Explicitly Using Constructors for Conversions

        1. An explicit constructor can be used to generate a conversion as long as we do so explicitly
        2. Making a constructor explicit turns off only the use of the constructor implicitly. Any constructor can be used to explicitly create a temporary object
        3. Ordinarily, single-parameter constructors should be explicit unless there is an obvious reason to want to define an implicit conversion. Making constructors explicit may avoid mistakes, and a user can explicitly construct an object when a conversion is useful

    11. 12.4.5. Explicit Initialization of Class Members

      1. Although most objects are initialized by running an appropriate constructor, it is possible to initialize the data members of simple nonabstract classes directly. Members of classes that define no constructors and all of whose data members are public may be initialized in the same way that we initialize array elements

        struct Data {
            int ival;
            char *ptr;
        };
        // val1.ival = 0; val1.ptr = 0
        Data val1 = { 0, 0 };
         
        // val2.ival = 1024;
        // val2.ptr = "Anna Livia Plurabelle"
        Data val2 = { 1024, "Anna Livia Plurabelle" };

      2. This form of initialization is inherited from C and is supported for compatibility with C programs. There are three significant drawbacks to explicitly initializing the members of an object of class type

        1. It requires that all the data members of the class be public
        2. It puts the burden on the programmer to initialize every member of every object. Such initialization is tedious and error-prone because it is easy to forget an initializer or to supply an inappropriate initializer
        3. If a member is added or removed, all initializations have to be found and updated correctly

      3. It is almost always better to define and use constructors. When we provide a default constructor for the types we define, we allow the compiler to automatically run that constructor, ensuring that every class object is properly initialized prior to the first use of that object


    Section 12.5 Friends



    1. In some cases, it is convenient to let specific nonmember functions access the private members of a class while still preventing general access

    2. The friend mechanism allows a class to grant access to its nonpublic members to specified functions or classes. A friend declaration begins with the keyword friend. It may appear only within a class definition. Friend declarations may appear anywhere in the class: Friends are not members of the class granting friendship, and so they are not affected by the access control of the section in which they are declared

    3. Ordinarily it is a good idea to group friend declarations together either at the beginning or end of the class definition

    4. Friendship: An Example


      1. A friend may be an ordinary, nonmember function, a member function of another previously defined class, or an entire class. In making a class a friend, all the member functions of the friend class are given access to the nonpublic members of the class granting friendship

    5. Making Another Class' Member Function a Friend


      1. When we declare a member function to be a friend, the name of the function must be qualified by the name of the class of which it is a member

    6. Friend Declarations and Scope


      1. Interdependencies among friend declarations and the definitions of the friends can require some care in order to structure the classes correctly

      2. More generally, to make a member function a friend, the class containing that member must have been defined. On the other hand, a class or nonmember function need not have been declared to be made a friend

      3. A friend declaration introduces the named class or nonmember function into the surrounding scope. Moreover, a friend function may be defined inside the class. The scope of the function is exported to the scope enclosing the class definition

    7. Overloaded Functions and Friendship


      1. A class must declare as a friend each function in a set of overloaded functions that it wishes to make a friend



    Section 12.6 static Class Members



    1. It is sometimes necessary for all the objects of a particular class type to access a global object. Perhaps a count is needed of how many objects of a particular class type have been created at any one point in the program, or the global object may be a pointer to an error-handling routine for the class, or it may be a pointer to the free-store memory for objects of this class type

    2. Ordinary, nonstatic data members exist in each object of the class type. Unlike ordinary data members, a static data member exists independently of any object of its class; each static data member is an object associated with the class, not with the objects of that class

    3. Just as a class may define shared static data members, it may also define static member functions. A static member function has no this parameter. It may directly access the static members of its class but may not directly use the nonstatic members

    4. Advantages of Using Class static Members


      1. The name of a static member is in the scope of the class, thereby avoiding name collisions with members of other classes or global objects

      2. Encapsulation can be enforced. A static member can be a private member; a global object cannot

      3. It is easy to see by reading the program that a static member is associated with a particular class. This visibility clarifies the programmer's intentions

    5. Defining static Members


      1. Amember ismade static by prefixing the member declaration with the keyword static. The static members obey the normal public/private access rules

    6. Using a Class static Member


      1. A static member can be invoked directly from the class using the scope operator or indirectly through an object, reference, or pointer to an object of its class type

      2. As with other members, a class member function can refer to a class static member without the use of the scope operator


    7. 12.6.1. static Member Functions


      1. When we define a static member outside the class, we do not respecify the static keyword.

      2. static Functions Have No this Pointer


        1. A static member is part of its class but not part of any object. Hence, a static member function does not have a this pointer. Referring to this either explicitly or implicitly by using a nonstatic member is a compile-time error

        2. Because a static member is not part of any object, static member functions may not be declared as const. After all, declaring a member function as const is a promise not to modify the object of which the function is a member. Finally, static member functions may also not be declared as virtual


    8. 12.6.2. static Data Members


      1. static data members can be declared to be of any type. They can be consts, references, arrays, class types, and so forth

      2. static data members must be defined (exactly once) outside the class body. Unlike ordinary data members, static members are not initialized through the class constructor(s) and instead should be initialized when they are defined

      3. The best way to ensure that the object is defined exactly once is to put the definition of static data members in the same file that contains the definitions of the class noninline member functions

      4. static data members are defined in the same way that other class members and other variables are defined. The member is defined by naming its type followed by the fully qualified name of the member

      5. As with any class member, when we refer to a class static member outside the class body, we must specify the class in which the member is defined. The static keyword, however, is used only on the declaration inside the class body. Definitions are not labeled static

      6. Integral const static Members Are Special


        1. Ordinarily, class static members, like ordinary data members, cannot be initialized in the class body. Instead, static data members are normally initialized when they are defined.

        2. When a const static data member is initialized in the class body, the data member must still be defined outside the class definition

        3. When an initializer is provided inside the class, the definition of the member must not specify an initial value

      7. static Members Are Not Part of Class Objects


        1. Ordinary members are part of each object of the given class. static members exist independently of any object and are not part of objects of the class type. Because static data members are not part of any object, they can be used in ways that would be illegal for nonstatic data members

        2. the type of a static data member can be the class type of which it is a member. A nonstatic data member is restricted to being declared as a pointer or a reference to an object of its class

        3. Similarly, a static data member can be used as a default argument

        4. A nonstatic data member may not be used as a default argument because its value cannot be used independently of the object of which it is a part. Using a nonstatic data member as a default argument provides no object from which to obtain the member's value and so is an error