Class 2: Access Control and Encapsulation (Learning Notes)

Encapsulation of classes is enhanced by using access descriptors.
    The members defined after the public descriptor can be accessed throughout the program, and the public members define the interface of the class.
    The members defined after the private descriptor can be accessed by the member functions of the class, and the private part conceals the implementation details of the class.

Example:

class Sales_data {
public:
Sales_data() = defult;
Sales_data(const std::string &s) :bookNo(s) {}
Sales_data(const std::string &s,unsigned n,double p):
bookNo(s),units_sold(n),revenue(p*n) {}
Sales_data(std::istream &s);
std::string isbn() const {return bookNo;}
Sales_data& combine(const Sales_data&);
private:
double avg_price() const {return units_sold ? revenue/units_sold : 0;};
std::string bookNo;
unsigned units_sold =0;
double revenue =0;
};

   ** Use class or struct keywords **
Using the struct keyword, members defined before the first access descriptor are public, and if using the class keyword, those members are private.

1. friends

    A class can allow other classes or functions to access its non-public members by making other classes or functions friend s. If class
 To make a function its friend, you just need to add a function declaration statement starting with the friend keyword.

Example:
     class  Sales_data {
      //Friend declarations for non-member functions of Sales_data
      friend Sales_data add(const Sales_data&,const Sales_data&);
      friend std::istream &read(std::istream&, Sales_data&);
      friend std::ostream &print(std::ostream&, const Sales_data&);
public:
        Sales_data() = defult;
        Sales_data(const std::string &s) :bookNo(s) {}
        Sales_data(const std::string &s,unsigned n,double p):
                   bookNo(s),units_sold(n),revenue(p*n) {}
        Sales_data(std::istream &s);
        std::string isbn() const {return bookNo;}
        Sales_data& combine(const Sales_data&);
 private:
        double avg_price() const  {return units_sold ? revenue/units_sold : 0;};
        std::string bookNo;
        unsigned units_sold =0;
        double revenue =0;
        };

    //Statement of non-member components of the Sales_data interface
    Sales_data add(const Sales_data&,const Sales_data&);
    std::istream &read(std::istream&, Sales_data&);
    std::ostream &print(std::ostream&, const Sales_data&); 
  ** Statement of Youyuan**
    If you want the user to call a friend function, we will make a special declaration of the function besides the declaration of the friend function. We usually make the declaration of the friend function.
Place it in the same header file as the class itself (outside the class).

2. Other features of classes

 Define two interrelated classes: Screen and Window_mgr

 ** Define a type member**
    class Screen{
     public:
          typedef std::string::size_type pos;
     private:
          pos cursor = 0;
          pos height =0; width =0;  //Three size_type members representing the position of the cursor and the height and width of the screen
          std:: string contents;   //Save Screen content
          };
 (1) Typeedef can also use type aliases equally, as follows:
       class Screen{
       public:  
       //Use type aliases to declare a type name equivalently
       using pos = std::string::size_type'
       }
  (2) Members used to define types must be defined before they are used.

   ** Screen class member function**
     class Screen{
     public:
          typedef std::string::size_type pos;
                             //Default constructors are required and must be explicitly declared
          Screen() =default; //Because Screen() has another constructor, this function is required. 
          //cursor is initialized to 0 by its class initial value
          Screen(pos ht,pos wd,char c):height(ht),width(wd),
          contents(ht *wd,c) {}                  
          char get() const                     //Read the character at the cursor
                 {return contents[cursor];}   //Implicit inline
          inline char get(pos ht, pos wd) const; //Display inline
          Scereen &move(pos r, pos c);
     private:
          pos cursor = 0;
          pos height =0; width =0;  //Three size_type members representing the position of the cursor and the height and width of the screen
          std:: string contents;   //Save Screen content
          };
 ** Make Members Inline Functions**

  The member functions defined within the class are automatically inlined. (Advantages of inline Functions: Improving Program Execution Efficiency)
  Inline is explicitly declared as part of the declaration inside the class. Similarly, inline keywords can be used outside the class to modify the definition of the function:

  ** Overloaded member functions**

  ** Variable Data Members**

  ** Initial values of class data members**
  In the new C++11 standard, a default initialization value can be assigned to the class definition.

3. Friendship among classes

    For example, add a member named clear to Window_mgr, which is responsible for setting the content of a specified Screen to blank. in order to
 To accomplish this task, clear needs to access the private members of Screen. To make this access legal, Screen needs to designate Window_mgr as its friend.
 class Screen {
              //Members of Window_mgr can access private parts of Screen classes
              friend class Window_mgr;
              //The remainder of the Screen class
              };
     If a class specifies a friend class, member functions of the friend class can access all members of the class, including non-public members in the class. Then, we can
 The clear members of Window_mgr are written as follows:
    class Window_mgr {
         public:
             // Number of each screen in the window
             using ScreenIndex = std::vector <Screen>::size_type;
             //Reset the specified Screen to blank by number
             void clear(ScreenIndex);
          private:
              std::vector <Screen> screens{Screen(24,80,'')};
           };
           void Window_mgr::clear(ScreenIndex i)
           {
              //s is a Screen reference to the screen we want to empty
              Screen &s =screen[i];
              //Reset the selected Screen blank
              s.contents = string(s.height *s.width,'');
           }
       ** Make member functions as friends**

  class Screen {
       // Window_mgr::clear must be declared before the Screen class
       friend void Window_mgr::clear(ScreenIndex);
  };

         ** Function Overload and Friends**
    If a class wants to declare a set of overloaded functions as its friends, it needs to declare each of these functions separately:  

    // Overloaded storeOn function
    extern std::ostream& storeOn(std::ostream&, Screen &);
    exterm BitMap& storeOn (BitMap &, Screen &);
    class Screen{
              //StorOn's ostream version has access to the private parts of Screen objects
              friend std::ostream& storeOn (std::ostream& ,Screen &);
    };
    ** Friendship Statement and Scope**      
    Defining the friend function inside the class, we must also provide the corresponding declaration outside the class to make the function visible. We're just making friends.
 The member of the metaclass calls the friend function, which must also be declared:
    struct X{
    friend void f() {/*Friend functions can be defined within a class*/}
    X() {f();}          //Error: f has not been declared yet
    void g();
    void h();
};

    void x::g() {return f():}   //Error: f has not been declared yet
    void f();                   //Declare the function defined in X
    void X::h(); {return f();}  //Right: Now the declaration of f is in scope    

Added by biodrux on Thu, 16 May 2019 10:06:22 +0300