Car rental system, including UML diagram, friend overloaded operator function, derived class use, file use, object array use, and the difference between protected and private

Learning objectives:

The program is to design a car rental system, which can realize the functions of car rental, canceling rental reservation, exiting the program and so on. File operation is required to store data. (this is my lesson plan. I plan to write him into a blog to consolidate my learning achievements)
Required design:
(1) Class design, including data members and member functions;
(2) Storing data in binary or ASCII files;
(3) Various operation functions of the administrator;
(4) Draw the UML diagram, implement the above functions as the member functions of the class, and write the main function to test the above functions.

Learning content:

1: The use of protected members and public members (the difference between protected and private), the use of derived classes and their reasons
2: Use of friend overload operator
3: Use of object arrays
4: Specific usage of derived classes
5: Use of documents

Explanation of learning content:

1: The use of protected members and public members (the difference between protected and private), the use of derived classes and their reasons

difference:
Private is completely private and can only be accessed by itself. Neither derived classes nor external can be accessed.
Protected is protected. Only derived classes can access it, but not externally.
Outside the class, if you want to use the members in the class, you can only directly use the public type. Protected and private cannot be accessed. For outside the class, the two are exactly the same.
Knowing their differences, we know that if you plan to use a derived class of a car (we know that a derived class can not only use the data members in the base class, but also add / use its own data members), in order to protect the data members, you should use protected instead of private. And the use of derived classes can make the objects you want to represent more accurate, such as cars, including cars, ambulances, etc. by using derived classes, you can more accurately describe the behavior of each object.

2: Use of friend overload operator

Format:

friend Function type operator operator(Formal parameter table)
{
	Function body
}		//Class internal definition

class X
{
	friend Function type operator operator(Formal parameter table);		//Intra class declaration
}

Function type operator operator(Formal parameter table)			//Out of class definition
{
	Function body 
}
notes;If the friend operator overloading function overloads the binocular operator, there are two operands in the parameter table; If overloaded unary operator, there is only one operand in parameter table.

Now let's talk about why we should use friend function overload operators.
We know that friend functions can directly access private members in the class (if you define them as friends in the class). Through this feature, if we overload the operator < <, and through certain operations, we can directly output the data of private members in the class. The specific codes are as follows:

 friend ostream & operator << (ostream& cout1, Car1& car);
        //The overload of the output constructor directly outputs all data member information of the automobile class
    //Define an operator overload as a friend function, so that you can directly access private members and improve efficiency
        //The return value is usually the type of the operated class, and the type of the parameter is the same as that of the operated class
        //Since the number of parameters overloaded by the operator is the same as the number of operands required by the operator, two parameters are required for the binocular operator
        
 ostream & operator << (ostream& cout1, Car1& car)//Overloading of operators<<
{             //The parameters are ostream class and Car1, so you can directly use the private members in Car1 class
              //Otherwise, directly using the cou`t output class carList[i] will report an error, even if it has a return value
    cout1 << setiosflags(ios::left) << setw(15) << car.getname();//Set to align left instead of right
    cout1 << setw(15) << car.getprice();
    cout1 << setw(25) << car.getcartype(); 
    cout1 << setw(15) << car.getnum() << setw(15) << car.getsize() << endl;
    return cout1;               //Returns a class reference of ostream
}

 void showCar(int i)                     //Output a person's information
        {
            //Cout < < name \ t \ tprice \ Ttype \ t\t \ tdays \ t \ tload \ T: "< < endl;
            cout << carList[i];             //If there is no operator overload, it cannot be used here                 
        }			

We can directly output the data in the array through the overloaded operator (we can directly introduce the data in our friend class) Friend operator overload

3: Use of object arrays

As the name suggests, object array means that each element in the array is a specific object of the class, and one object after another has the data members and member functions of the class. Each special object is represented by using the method of array subscript (this is a bit similar to the use of function array, that is, each element in the array is a function. For the specific function array, see my previous articles). Let's introduce the usage:
Function array preliminary
Function array drill down

  Car1 carList[20];    //Declare a Car1 object array containing name price cartype num size
  
 void insert(string N, float P, const string C, const int Num, const int S)//Add rental information
        {
            carList[carNum].setname(N);
            carList[carNum].setprice(P);
            carList[carNum].setcartype(C);
            carList[carNum].setnum(Num);
            carList[carNum].setsize(S);
            carNum++;                   //Add 1 for each rental information
        }

The above is how to use the object array.

4: Specific usage of derived classes

Relationship between derived class and base class:

  1. The derived class object stores the data members of the base class
  2. Derived class objects can use the methods of the base class
    Since it is necessary to build a derived class, it shows that the original base class can not meet the needs of the program, so the derived class should have its own constructor, and the required data members and member functions can be added. It is this feature that makes the objects constructed in derived classes more accurate.
class Car			//Base class
{
protected:
    string name;                        //Name of lessee
    float price;                        //Car price
public:             //These shorter functions can be used directly with inline
    Car();                              //Default constructor 
    Car(const string N, const float P); //overloaded constructor 
    void setname(const string N);       //Set lessee name       
    void setprice(const float P);       //Set the number of car prices
    string getname();                   //Get the tenant's name
    float getprice();                   //Get the car price
};

class Car1 :public Car
{
protected:
    //Derived classes can use several classes. The following are the base classes
    //string name;                        // Name of lessee
    //float price;                        // Car price
    string cartype;                       //Car type
    int num;                              //Lease days
    int size;                             //Vehicle load
public:
    Car1();//Parameterless constructor to set default values for car color, quantity and load.
    Car1(const string N, const float P, const string C, const int Num, const int S);//Constructor with parameters to set car color, quantity and load
    void setcartype(const string C);      //Set car type
    void setnum(const int Num);           //Set lease days
    void setsize(const int S);            //Set vehicle load
    string getcartype();                  //Get car type
    int getnum();                         //Get days
    int getsize();                        //Get load    
    friend ostream & operator << (ostream& cout1, Car1& car);
        //The overload of the output constructor directly outputs all data member information of the automobile class
};  

You can find that derived classes have more methods.

Special relationship between derived class and base class:
As defined in the book:
1. The base class pointer can point to the derived class object without explicit type conversion;
2. Base class references can reference derived class objects without explicit type conversion;
Of course, when we talk about people, we can see the following examples:
DerivClass Mike;
BaseClass &rt = Mike;
BaseClass *pt = &Mike;
Pointers and references are of BaseClass type, so rt.Name() and Pt - > name() are legal.

BaseClass Jake; DerivClass &rr = Jake; DerivClass *pr = &Jake;
Pointers and references are of derived class DerivClass type, RR Both name() and PR - > name() are illegal. Why?
Imagine that if the base class reference can reference the derived class object, you can use the base class reference to call the method of the derived class object, because the derived class inherits the method of the base class, and it is no problem for the base class to call the derived class.
If a derived class reference can reference a base class object, there is a problem. Because there may be methods in the derived class that the base class does not have, it will be uncertain to use the derived class instead of the base class, which is not allowed by the compiler.
In a word, we can think of it as follows: derived classes contain base classes. If there are fewer calls, there will be no problem. If there are more calls, there may be problems. As shown below:

5: Use of documents

The use of C + + files requires the introduction of header files

#Include < fstream > / / input / output header file of the file

This is because both writing and reading files need to use input and output streams, so we need to introduce such a file.

void readFile()//File reading
        {
            float price;
            int num, size, Num;
            char name[20], cartype[20];
            ifstream infile("D:\\data.txt");//The definition file pointer infile points to data txt
            if (!infile.is_open())      //Judge whether it is successfully opened
            {
                cerr << "Open failed!\n";
                return;
            } // while(!infile.eof()) / / why use infile.eof What about EOF () errors
            while ( infile >> name )      //If the read data is empty, the cycle ends
            {                           //The reading order can be disturbed, but the order must also be changed when the main function is input
                infile >> price;           //This is because the read in is sequential rather than type        
                infile >> cartype;           //Suppose you first read the price, which is a float       
                infile >> num;           //The first thing you enter is a string, so you will directly determine the failure as false   
                infile >> size;
                insert(name, price, cartype, num, size);
            }
            cout << "The lease information read from the file includes:" << endl;
            showAll();
            infile.close();
        }
        void writeFile()//Modification of documents
        {
            ofstream outfile("D:\\data.txt", ios::out);
            if (!outfile.is_open())
            {   
                cerr << "Cannot open data.txt\n";
                exit(-1);
            }

In this article, I planned to use infile The eof () function also modified the data in the data and added eof, but it was found that it did not work. On the day of reply, I planned to ask the teacher, but I would reply the reason in the comment (because I was too lazy to CSDN myself and had no exact answer).



UML diagram:

Don't post the complete code (after all, I wrote several unnecessary functions in order to count the words)

Keywords: C++ Programming

Added by ravegti on Fri, 11 Feb 2022 19:33:46 +0200