C + + class constructor friend

C + + class notes

1, Class

The basic idea of class is abstraction and encapsulation. Class, including three parts:

  • Data member of class
  • Function body responsible for interface implementation
  • Define the various private functions required by the class

It should be noted that the declaration of member function must be inside the class, and its definition can be inside or outside the class.

The following is an example of a class:

Sales_data total; //Define total as Sales_data class

struct Sales_data
{
    //Declaring member functions: about sales_ Operation of data object
    std::string isbn() const { return bookNo}; 
    Sales_data& combine(const Sales_data&);
    double avg_price() const;

    //Data member
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

//Define member functions outside the class
double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}

Sales_data& Sales_data::combine(const Salse_data &rhs)
{
    units_sold += rhs.units_sold; //Add members of rhs to members of this object
    revenue += rhs.revenue;
    return *this;
}

Specify the following points:

  1. There is a concept of this
    In the member function, there is an isbn(), which returns bookno. In fact, it implicitly returns total bookNo. The member function accesses the object calling it through an additional implicit parameter called this. This is a constant pointer and it is not allowed to change the address saved in this. It can also be written as return this - > bookno, But it's not necessary.

  2. Class scope and member function
    It is worth noting that even if bookNo is defined after the isbn() function, isbn can still use this variable. The compiler handles classes in two steps: first compile the member declaration, and then the member function body. Therefore, the member function body can use other members in the class at will, regardless of the order in which these members appear.

  3. Define member functions outside the class
    When defining a member function outside the class, the return type, parameter list and function name must be consistent with those declared in the class, and the name of the member defined outside the class must include its class name.

  4. Define a function that returns this object
    The combine function returns * this, that is, dereference the this pointer to obtain the object executing the function, that is, return the reference of total.

2, Constructor

Each class defines how its object is initialized. A class controls the initialization process of its object through one or several special member functions, which are called constructors. Therefore, the task of the constructor is to initialize the data members of the class object. Whenever the class object is created, the constructor will be executed.

The constructor name is the same as the class name. Constructors have no return type and cannot be declared const. A class can contain multiple constructors, but the number or type of parameters must be different between different constructors.

Above statement

Sales_data total

Initialization is not provided, but the class controls the default initialization process through a special constructor. This function is the default constructor. The default constructor does not require any arguments. The constructor created by the compiler is also called the synthetic default constructor.

Although the above example can be used, it is worth noting that some classes cannot rely on the default constructor for initialization for the following reasons:

  • The compiler will generate a default constructor for us only if it finds that the class does not contain any constructor.
  • The synthesized default constructor may perform the wrong operation.
  • The compiler cannot synthesize default constructors for some classes.

Now, based on the above example, add a constructor:

Sales_data total; //Define total as Sales_data class

struct Sales_data
{
    //New constructor
    Sales_data() = default;
    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 &);

    //Declaring member functions: about sales_ Operation of data object
    std::string isbn() const { return bookNo}; 
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
    //Data member
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

//Define member functions outside the class
double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}

Sales_data& Sales_data::combine(const Salse_data &rhs)
{
    units_sold += rhs.units_sold; //Add members of rhs to members of this object
    revenue += rhs.revenue;
    return *this;
}
//Define a constructor outside the class
Sales_data::Sales_data(std::istream &is)
{
    read(is, *this)//Read is used to read a transaction information from is and store it in this object
}

Specify the following points:

  1. =Meaning of default
    The constructor does not accept any arguments, so it is a default constructor. We define this constructor only because we need both other forms of constructors and default constructors. We want this function to work exactly like the composite default constructor we used earlier.

  2. Constructor initializer list

        Sales_data(const std::string &s): bookNo(s) {}
    

    This only takes the bookNo member for initialization. The initialization of other data members is implicitly initialized in the same way as the composite default constructor.

        Sales_data(const std::string &s, unsigned n, double p):
         bookNo(s), units_sold(n), revenue(p*n) {}
    

    This constructor initializes all data members.
    You can see that the function bodies in the above two constructors are empty. This is because the only purpose of these constructors is to assign initial values to data members. Once no other tasks need to be performed, the function body will be empty.

  3. Define a constructor outside the class
    Define the constructor outside the class, and you can see the Sales_data::Sales_data defines sales_ The member of the data class, and then the name is the same as the name of the class. So it's a constructor.

3, Access control and encapsulation

So far, the above example has not been encapsulated. Therefore, the access specifier is introduced to strengthen the encapsulation of the class. There are mainly two keywords: public and private. Members after the public specifier can be accessed in this program, and only members of the private class can be accessed.
Specific examples are:

Sales_data total; //Define total as Sales_data class

class Sales_data
{
    public:
        //New constructor
        Sales_data() = default;
        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 &);

        //Declaring member functions: about sales_ Operation of data object
        std::string isbn() const { return bookNo}; 
        Sales_data& combine(const Sales_data&);
        double avg_price() const;
    private:
        //Data member
        std::string bookNo;
        unsigned units_sold = 0;
        double revenue = 0.0;
};

//Define member functions outside the class
double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}

Sales_data& Sales_data::combine(const Salse_data &rhs)
{
    units_sold += rhs.units_sold; //Add members of rhs to members of this object
    revenue += rhs.revenue;
    return *this;
}
//Define a constructor outside the class
Sales_data::Sales_data(std::istream &is)
{
    read(is, *this)//Read is used to read a transaction information from is and store it in this object
}

Specify the following points:

  1. A class can contain 0 or more access specifiers.
  2. The above replaces struct with class. The only difference between the two is that the default access permissions of struct and class are different. In other words, a class can define members before its first access specifier, and access to such members depends on how the class is defined. If we use the struct keyword, the members defined before the first access specifier are public. Conversely, if we use the class keyword, these members are private. When we want all members of the defined class to be public, use struct. If any member is private, use class.

The advantage of encapsulation is that the class author can modify the data freely. As long as the interface remains unchanged, the user code does not need to be changed. Secondly, encapsulation can prevent data from being destroyed due to user reasons.

4, Friends

If some data members are private, some functions cannot be compiled. Class can allow other classes or functions to access its non-public members by calling other classes or functions its friends. Just add the friend keyword.
Specific examples:

Sales_data total; //Define total as Sales_data class

class Sales_data
{
    //For sales_ Friend declaration made by nonmember function of 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:
        //New constructor
        Sales_data() = default;
        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 &);

        //Declaring member functions: about sales_ Operation of data object
        std::string isbn() const { return bookNo}; 
        Sales_data& combine(const Sales_data&);
        double avg_price() const;
    private:
        //Data member
        std::string bookNo;
        unsigned units_sold = 0;
        double revenue = 0.0;
};

//Define member functions outside the class
double Sales_data::avg_price() const
{
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}

Sales_data& Sales_data::combine(const Salse_data &rhs)
{
    units_sold += rhs.units_sold; //Add members of rhs to members of this object
    revenue += rhs.revenue;
    return *this;
}
//Define a constructor outside the class
Sales_data::Sales_data(std::istream &is)
{
    read(is, *this)//Read is used to read a transaction information from is and store it in this object
}



//Sales_ Declaration of non member components of the 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&);

In general, it is best to declare friends in a set before the beginning or end of a class definition.

Keywords: C++

Added by xplosiongames on Thu, 20 Jan 2022 01:16:56 +0200