Object oriented programming idea
1, Memory partition model
When the C + + program is executed, the memory is divided into four areas
- Code area: it stores the binary code of the function body, which is managed by the operating system
- Global area: store global variables, static variables and constants
- Stack area: automatically allocated and released by the compiler to store the parameter values and local variables of the function
- Heap area: it is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program
The meaning of four memory areas: the data stored in different areas gives us different life cycles and gives us greater flexibility in programming
1. Before program execution
After the program is compiled, it is generated exe class executes the program. Before executing the program, it is divided into two areas
Code area
- Store mechanical commands executed by CPU
- The code area is shared. The purpose of sharing is to have only one code in memory for programs that are frequently executed
- The code area is read-only because it prevents the program from accidentally modifying its instructions
Global area
- Global and static variables are stored here
- The global area also includes a constant area, where string constants and other constants are also stored
- The number of this area is released by the operating system at the end of the program
#include <iostream> using namespace std; // global variable int global_a = 10; int global_b = 10; // Global constant const int c_g_a = 10; const int c_g_b = 10; int main() { // Global area // Global variable, static variable, constant // Static variable static int static_a = 10; static int static_b = 10; // constant // string constant cout << "The address of the string constant is " << (int)&"hello" << endl; // const modified variable // const modified global variable // const modified local variable const int c_l_a = 10; const int c_l_b = 10; // Create a normal local variable int a = 10; int b = 10; cout << "local variable a Your address is " << (int)&a << endl; cout << "local variable b Your address is " << (int)&b << endl; cout << "Local constant c_l_a Your address is " << (int)&c_l_a << endl; cout << "Local constant c_l_b Your address is " << (int)&c_l_b << endl; cout << "global variable global_a Your address is " << (int)&global_a << endl; cout << "global variable global_b Your address is " << (int)&global_b << endl; cout << "Static variable static_a Your address is " << (int)&static_a << endl; cout << "Static variable static_b Your address is " << (int)&static_b << endl; cout << "Global constant c_g_a Your address is " << (int)&c_g_a << endl; cout << "Global constant c_g_b Your address is " << (int)&c_g_b << endl; }
2. After the program runs
Stack area
- It is automatically allocated and released by the compiler to store the parameter values and global variables of the function
- Note: do not return the address of local variables. The data opened up in the stack area is automatically released by the compiler
#include <iostream> using namespace std; int* func(int b) { // The formal parameter data will also be placed in the stack area b = 100; int a = 10; // Local variables are in the stack area and are cleared after the function is run return &a; // Return the address of local variable, illegal function } int main() { cout << *func() << endl; // The first time you can print the correct number is because the compiler makes a reservation cout << *func() << endl; // The second data may not be retained }
Heap area
- It is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program
- In C + +, new is mainly used to open up memory in heap area
#include <iostream> using namespace std; int* func() { // The new keyword can be used to open up data to the heap area int* p = new int(10); // The pointer is also a local variable in nature. It is placed on the stack, and the data saved by the pointer is placed on the heap return p; } int main() { // Open up data in the heap area int* p = func(); cout << *p << endl; }
3. new operator
Using new operator in C + + to open up data in heap
The amount of data opened up in the heap area is manually opened up and released by the programmer. The release uses the operator delete
Syntax: new data type
The data created with new will return the pointer of the type corresponding to the data
#include <iostream> using namespace std; int* func() { // The new method opens up an array int* p = new int(10); // Returns a pointer to the data type return p; } void test() { //Create an array of 10 integer data in the heap area int* arr = new int[10]; // 10 means that the array has 10 elements for (int i = 0; i < 10; i++) { arr[i] = i; // Assign a value to an array } // Release the heap array. When releasing the array, add [] delete[] arr; } int main() { int* p = func(); cout << *p << endl; // The data in the heap area is managed by the programmer delete p; // The data has been released, and it is illegal to access it again cout << *p << endl; test(); }
2, Quote
1. Basic use
Function: alias variables
Syntax: data type & alias = variable name;
#include <iostream> using namespace std; int main() { // Reference basic syntax // Data type & alias = variable name int a = 10; int& b = a; cout << b << endl; b = 100; cout << a << endl; }
2. Precautions
- References must be initialized
- The reference cannot be changed after initialization
#include <iostream> using namespace std; int main() { int a = 10; // References must be initialized int& b = a; // int &b; // Illegal operation // Once a reference is initialized, its address cannot be changed, but it can be assigned }
3. Reference as function parameter
Function: when passing a function parameter, you can use the reference technology to make the formal parameter modify the argument
Advantages: the pointer can be modified
#include <iostream> using namespace std; // Exchange function // 1. Value transfer void swap(int a,int b) { int temp = a; a = b; b = temp; } // 2. Address delivery void swap1(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 3. Reference passing void swap3(int &a, int &b) { // &A is the alias, which can be the same as the variable name int temp = a; a = b; b = temp; } int main() { int a = 10; int b = 20; cout << a << b << endl; cout << "Run function" << endl; swap(a, b); cout << a << b << endl; // The arguments have not changed cout << a << b << endl; cout << "Run function" << endl; swap1(&a, &b); cout << a << b << endl; // Argument changed cout << a << b << endl; cout << "Run function" << endl; swap3(a, b); cout << a << b << endl; // Argument changed }
The effect of referencing parameters is the same as passing by address, and the syntax of reference is clearer and simpler
4. Reference the return value of the function
Function: a reference can exist as the return value of a function
Note: do not return references to local variables
Usage: function call as lvalue
#include <iostream> using namespace std; // Reference the return value of the function // 1. Do not return a reference to a local variable int& test1() { // Adding & is equivalent to returning by reference int a = 10; // Local variables are stored in the stack area in four areas return a; } // 2. Function can be called as an lvalue int& test2() { static int a = 10; // Static variables are stored in the global area, and the data on the global area is released by the system after the program is completed return a; } int main() { int& b = test1(); cout << b << endl; cout << b << endl; int& c = test2(); cout << c << endl; test2() = 1000; // The left value of the memory can be modified as the address of the function cout << c << endl; }
5. Essence
Essence: the essence of reference is a pointer constant implemented in C + +
6. Constant reference
Function: constant reference is mainly used to modify formal parameters to prevent misoperation
Use in function parameter list
#include <iostream> using namespace std; // print data void showValue(int &a) { // const can be added to prevent misoperation a = 1100; cout << a << endl; } int main() { // Constant reference: used to modify formal parameters to prevent misoperation int a = 10; const int& ref = 10; // After const is added, the compiler modifies the code to int temp = 10; const int & ref = temp; // ref = 20; // After adding const, it becomes read-only showValue(a); cout << a << endl; }
3, Function improvement
1. Default parameters
In C + +, the formal parameters in the formal parameter list of a function can have default values
Syntax: return value type function name (parameter = default) {}
#include <iostream> using namespace std; // Default parameters for function void func(int a , int b = 10) { // You can also pass in parameters. If you pass in parameters, you can use custom parameters. Otherwise, you can use default parameters cout << a << "\t" << b << endl; } // matters needing attention // If a location already has a default parameter, it must have a default value from this location // If the function declaration has default parameters, the function implementation cannot have default parameters and cannot redefine parameters, that is, only one declaration and implementation can have default parameters void func(int a, int b); int main() { int a = 20; // int b = 30; func(a); }
2. Occupancy parameter
There can be placeholder parameters in the formal parameter list of functions in C + +, which are used for placeholder. This position must be filled when calling functions
Syntax: return value type function name (data type) {}
#include <iostream> using namespace std; // Placeholder parameter: there can be default parameters // Return value type function name (data type) {} void func(int a, int) { cout << "this is func" << endl; } void func(int a, int); int main() { func(10, 20); }
3. Function overloading
3.1 general
Function: function names can be the same to improve the reusability of function names
Conditions for function overloading
- Under the same scope
- Same function name
- Function parameters have different types, numbers or orders
Note: the return value of a function cannot be used as a condition for function overloading
#include <iostream> using namespace std; // function overloading // Under the same scope // Same function name // The type, number or order of function parameters are different void func(double a, int b) { cout << "10" << endl; } void func(string name) { cout << name << endl; } void func(int a, double b) { cout << "1010" << endl; } int main() { func("hello"); func(1.0, 20); func(20, 1.0); }
3.2 precautions
- Reference as overload condition
- Function overload encountered function default parameter
#include <iostream> using namespace std; // Precautions for function overloading // 1. Reference as overload condition void func(int& a) { cout << "func(int &a)call" << endl; } void func(const int& a) { cout << "func(const int &a)call" << endl; } // 2. The default parameters encountered by function overloading will be ambiguous void func2(int a, int b = 10) { cout << "func(int a Default parameters)call" << endl; } void func2(int a) { cout << "func(int a)call" << endl; } int main() { const int a = 10; int b = 20; func(a); func(b); func2(a, b); }
4, Classes and objects
Three characteristics of C + + object-oriented: encapsulation, inheritance and polymorphism
C + + believes that everything has attributes and behavior
1. Encapsulation
1.1 significance of packaging
Encapsulation is one of the three characteristics of C + + object-oriented
Meaning of encapsulation
-
Take attributes and behaviors as a whole to express things in life
When designing classes, attributes and behaviors are written together to represent things
Syntax: class name {access rights: attribute / behavior};
// Set a circle class and find its circumference #include <iostream> using namespace std; // PI const double PI = 3.14; class Circle { // Access rights: public rights public: // Attributes: radius int m_r; // Behavior: get the circumference of a circle double calcculate() { return 2 * PI * m_r; } }; int main() { // Create objects (instanced objects) through the circle class Circle c1; // Assign a value to the attribute of the circle object c1.m_r = 10; cout << "The circumference of the circle is" << c1.calcculate() << endl; }
Case: design a student class with the attributes of name and student number. You can assign values to the name and student number, and display the student's name and student number
#include <iostream> using namespace std; #include <string>; class Student { // Access rights public: // attribute string stu_name; int stu_id; // behavior void showInfo() { cout << "full name:" << stu_name << " Student number:" << stu_id << endl; } // Assign values to attributes void setInfo(string name, int id) { stu_name = name; stu_id = id; } }; int main() { Student stu; // instantiation stu.setInfo("Zhang San", 1); stu.showInfo(); }
The properties and behaviors in a class are called members
Member attribute, member variable, member method / member function
-
Control attributes and behaviors with permission
When designing classes, attributes and behaviors can be controlled under different permissions
Access rights are
- Public public permission
- Protected protected permissions
- Private private rights
#include <iostream> using namespace std; #include <string>; // public members can be accessed inside the class or outside the class // Protected members can be accessed inside the class, not outside the class, and sons can also access the contents protected by their fathers // Private members can be accessed within the class, not within the class, and sons cannot access the private content of their fathers class Person { // Public authority public: string name; // Protection Authority protected: string car; // Private rights private: int money; public: void func() { name = "zhansan"; car = "tuolaji"; money = 20; } }; int main() { // Instantiate concrete objects Person p1; p1.name = "lishi"; // p1.car = "benc"; // The protection permission cannot be accessed outside the class // p1.money = 30; // Private permission content cannot be accessed outside the class }
1.2 differences between struct and class
In C + +, the only difference between struct and class is that the default access permissions are different
- The default permission of struct is public
- class default permission is private
#include <iostream> using namespace std; #include <string>; class C1 { int A; // The default permission is private }; struct C2 { int A2; // Default public }; int main() { // struct default public C2 c2; c2.A2 = 100; // Can access // class default private C1 c; // c.A = 100; // Cannot modify }
1.3 privatization of member attributes
advantage
- Set all member properties to private, and you can control the read and write permissions yourself
- For write permission, we can check the validity of data
#include <iostream> using namespace std; #include <string>; // Privatization of member properties class Person { public: // Set name and obtain permission void setName(string pname) { name = pname; } string getName() { return name; } /* // Get age int getAge() { age = 18; // Initialize to 18 years old return age; } */ // Readable and writable age, if you want to modify it (the age range must be 0 to 18 years old) int getAge() { return age; } // Set age void setAge(int num) { if (num < 0 || num > 18) { age = 15; cout << "There is a problem with the age you entered" << endl; return; } cout << num << endl; age = num; } // Write only property void setMoney(int num) { money = num; } private: // Set all private // The name is readable and writable string name; // Age read only int age; // Property only write int money; }; int main() { Person p; p.setName("Zhang San"); cout << "name:" << p.getName() << endl; p.setAge(150); // If the entered value does not meet the requirements, the assignment is directly forced cout << "Age:" << p.getAge() << endl; }
1.4 cases
Design a Cube class (Cube), calculate the area and volume of the Cube, and judge whether the two cubes are equal by global function and member function respectively
#include <iostream> using namespace std; // Create a legislative class class Cube { // Design properties private: int c_l; // long int c_h; // high int c_w; // wide // Behavior gets the area and volume of the cube public: // set a property void setInfo(int l, int w, int h) { c_l = l; c_w = w; c_h = h; } // get attribute int getL() { return c_l; } int getH() { return c_h; } int getW() { return c_w; } // Get area int getS() { return c_l * c_h * 2 + c_l * c_w * 2 + c_h * c_w * 2; } // Get volume int getV() { return c_l * c_h * c_w; } // Member functions determine whether they are equal bool isSameByClass(Cube& c) { if (getH() == c.getH() && getW() == c.getW() && getL() == c.getL()) { return true; } return false; } }; // Use global function and member function to judge whether two cubes are equal // Global function bool isSame(Cube &c1, Cube &c2) { // Reference passing if (c1.getH() == c2.getH() && c1.getW() == c2.getW() && c1.getL() == c2.getL()) { return true; } return false; } int main() { // First cube Cube c1; c1.setInfo(1, 1, 1); int s1 = c1.getS(); // volume int v1 = c1.getV(); // the measure of area // Second cube Cube c2; c2.setInfo(1, 1, 2); int s2 = c2.getS(); int v2 = c2.getV(); if (isSame(c1, c2)) { cout << "identical" << endl; } else { cout << "inequality" << endl; } if (c1.isSameByClass(c2)) { cout << "Member judgment, same" << endl; } else { cout << "Member judgment, different" << endl; } }
Judge the position of the point on the circle
#include <iostream> using namespace std; // Judge the relationship between point and circle // Point class class Point { private: int x; int y; public: void setPoint(int x, int y) { x = x; y = y; } int getx() { return x; } int gety() { return y; } }; // Circular class class Circle { private: int r; // radius Point circlePoint; // Represents the center of a circle public: void setR(int r) { r = r; } int getR() { return r; } void setCenter(Point center) { circlePoint = center; } Point getCenter() { return circlePoint; } }; // Judge the relationship between point and circle void isInCircle(Circle &c, Point &p) { // Calculate the square of the distance if (pow(c.getCenter().getx() - p.getx(), 2) - pow(c.getCenter().gety() - p.gety(), 2) == pow(c.getR(), 2)) { cout << "Point on circle" << endl; return; } cout << "The point is not on the circle" << endl; } int main() { // Create circle Circle c; Point ct; ct.setPoint(10, 0); c.setCenter(ct); c.setR(10); Point p; p.setPoint(10, 10); isInCircle(c, p); }
A class can instantiate another class as its attribute
2. Object initialization and cleanup
- In life, the electronic products we buy basically have factory settings. One day, when we are not in use, we delete some of our own information data to ensure security
- Object orientation in C + + comes from life. Each object has initialization settings and data cleaning settings before object destruction
2.1 constructors and analytic functions
Object initialization and cleanup are also two very important security issues
- An object or variable has no initial state, and the consequences of its use are unknown
- Similarly, after using an object or variable, it will also cause some security problems if it is not cleaned up in time
C + + uses constructors and destructors to solve the above problems. These two functions will be automatically called by the compiler to complete object initialization and cleaning
The initialization and cleanup of objects are what the compiler forces us to do, so if we don't provide constructors and destructors, the compiler will provide them
The constructor and destructor provided by the compiler are empty
- Constructor: its main function is to assign value to the member attribute of the object when creating the object. The constructor is automatically called by the compiler without manual call
- Destructor: the main function is that the system will automatically call and perform some cleaning work before the object is destroyed
Constructor syntax: class name () {}
- Constructor, no return value and no void
- The function name is the same as the class name
- Constructors can have arguments or overloads
- When the program calls the object, it will automatically call the construction without manual call, and it will only be called once
Destructor syntax: ~ class name () {}
- Destructor, no return value, no void
- The function name is the same as the class name, preceded by a symbol~
- Destructors cannot have parameters, so overloading cannot occur
- The program will automatically call the destructor before the object is destroyed. There is no need to call it manually, and it will only be called once
#include <iostream> using namespace std; class Person { public: // Constructor Person() { cout << "Person Call of constructor" << endl; } // Destructor ~Person() { cout << "Person Call of destructor" << endl; } }; // Construction and deconstruction are necessary implementations. If we don't provide them ourselves, the compiler will provide the construction and Deconstruction of an empty implementation void test() { Person p; // The data on the stack will be automatically released after the test is executed } int main() { // Object initialization and cleanup //test(); Person p; system("pause"); return 0; }
2.2 classification and calling of constructors
Two classification methods
- Classification by parameters: parametric structure and nonparametric structure
- Classification by construction and common copy type
Three call modes
- bracketing
- Display method
- Implicit transformation method
#include <iostream> using namespace std; // Classification and calling of constructors class Person { public: int age; // Constructor // Nonparametric structure Person() { cout << "Person Call of constructor" << endl; age = 1; } // Parametric structure Person(int a) { age = a; cout << "Person Constructor calls have arguments" << a << endl; } // copy constructor Person(const Person &p) { // Copy all the attributes of the incoming person to me age = p.age; cout << "Person Call copy of constructor" << age << endl; } }; void test() { // call // bracketing Person p; // Call of default constructor Person p02(10); // Call parameterized constructor Person p03(p02); // Call of copy constructor //Cout < < P2's age is: < < P2 age << endl; //Cout < < P3's age is: < < P3 age << endl; // Display method Person p1; Person p2 = Person(10); // Parametric structure Person p3 = Person(p2); // copy construction //Person(10); // Anonymous object, features: after the execution of the current line, the system will immediately recycle the anonymous object // Implicit transformation method Person p4 = 10; // Equivalent to Person p4 = Person(10); Person p5 = p4; } int main() { test(); }
matters needing attention
-
When calling the default constructor, do not add ()
-
Because of the following line of code, the compiler will consider it a declaration of a function
Person p1();
-
-
Do not use copy constructors to initialize anonymous objects
-
Because the compiler will think that Person p4(p3) === Person p3;, Declaration that it is an object
Person p4(p3);
-
2.3 call timing of copy function
The timing of copying function calls in C + + usually consists of three cases
- Initialize a new object with an already created object
- Value is passed to function parameters
- Returns a local object as a value
#include <iostream> using namespace std; // Call timing of copy constructor class Person { public: Person() { cout << "Default function" << endl; } Person(int age) { age = age; cout << "Parametric function" << endl; } Person(const Person& p) { age = p.age; cout << "copying functions " << endl; } ~Person() { cout << "Class is released" << endl; } int age; }; void test01() { // Initialize a new object with an already created object Person p1(20); Person p2(p1); cout << p2.age << endl; } void doWork( Person p ) { cout << "doWork" << endl; } void test02() { // Value is passed to function parameters Person p; doWork(p); } Person doWork02() { Person p1; return p1; } void test03() { // Returns a local object as a value Person p = doWork02(); } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
2.4 constructor calling rules
By default, the C + + compiler adds at least three functions to a class
- Default constructor (no parameters, empty function body)
- Default destructor (no parameters, empty function body)
- The default copy function copies the values of attributes
Constructor call rule
- If the user defines a parametric constructor, the default nonparametric constructor will not be provided in C + +, but the default copy constructor will be provided
- If you define a copy constructor, C + + will not provide another constructor
#include <iostream> using namespace std; // Call rules for constructors // 1. Create a class, and the C + + compiler will add at least three functions to each class, including destructor, default function and copy function // If the user defines a parametric constructor, the default nonparametric constructor will not be provided in C + +, but the default copy constructor will be provided class Person { public: //Person() { // Cout < < default function call < < endl; //} ~Person() { cout << "Destructor call" << endl; } int age; Person(int age) { age = age; cout << age << endl; } //Person(const Person &p) { // age = p.age; // Cout < < copy constructor < < endl; // } }; //void test1() { // Person p; // p.age = 18; // Person p2(p); // cout << p2. Age < < copy < < endl// Automatic call to copy function //} void test2() { Person p(10); Person p2(p); cout << p2.age << "Copy" << endl; } int main() { //test1(); test2(); }
2.5 deep copy and light copy
Deep copy: a simple assignment copy operation
Shallow copy: re apply for space in the heap area for copy operation
#include <iostream> using namespace std; // Deep copy, shallow copy class Person { public: int age; int* height; Person() { cout << "Person Default constructor call for" << endl; } Person(int age_, int height_) { cout << "Person Parameterized constructor call" << endl; age = age_; height = new int(height_); // Create height data into the heap area } Person(const Person& p) { cout << "Person Copy constructor call" << endl; age = p.age; // height = p.height; // The compiler implements this line of code by default -- a shallow copy // Deep copy operation height = new int(*p.height); } ~Person() { // Open up the operation area of code analysis and release the data if (height != NULL) { delete height; height = NULL; // Avoid wild pointers } cout << "Person Destructor call" << endl; } }; void test() { Person p1(18, 160); cout << "p1 Your age is" << p1.age << " p1 Your height is" << *p1.height <<endl; Person p2(p1); // If you use the copy constructor provided by the compiler, you will do a shallow copy operation; The problem with shallow copy is that the memory in the heap will be released repeatedly // This problem needs to be solved by deep copy cout << "p2 Your age is" << p2.age << " p2 Your height is" << *p2.height <<endl; } int main() { test(); system("pause"); return 0; }
2.6 initialization list
effect
- C + + provides initialization list syntax to initialize attributes
Syntax: constructor (): Property 1 (value 1) property 2 (value 2) {}
#include <iostream> using namespace std; // Initialization list class Person { public: // Traditional initialization operation: use the parameter passing constructor to operate // Initialization list initialization properties // Person() :a(10), b(20), c(30) { // } // More flexible initialization Person(int a, int b, int c) :a(a), b(b), c(c) { } int a; int b; int c; }; void test() { Person p(20, 30, 50); cout << "establish P" << endl; cout << p.a << p.b << p.c << endl; } int main() { test(); system("pause"); return 0; }
2.7 class objects as class members
A member in a C + + class can be an object of another class, which we call an object member
class A {} class B { A a; // Class B has object A as A member and A as an object member }
Then, when creating A B object, which is the construction and deconstruction order of A and B?
#include <iostream> using namespace std; // Class object as class member class Phone { public: string c_Pname; Phone(string pName) { c_Pname = pName; cout << "phone Constructor" << endl; } ~Phone() { cout << "Phone Destructor" << endl; } }; class Person { public: string c_Name; Phone c_Phone; Person(string name, string pName): c_Name(name), c_Phone(pName) { cout << "person Constructor" << endl; } ~Person() { cout << "person Destructor" << endl; } }; void test() { Person p("Zhang San", "Fruit 13 ProMax"); cout << "c_Name:" << p.c_Name << " c_Phone:" << p.c_Phone.c_Pname << endl; } int main() { test(); system("pause"); return 0; }
The order of construction is: first call the construction of object members, and then call the construction of this class
The order of deconstruction is opposite
2.8 static members
Static members are called static members by adding the keyword static before member variables and member functions
Static members are divided into
- Static member variable
- All objects share the same data
- Allocate memory at compile time
- In class declaration, out of class initialization
- Static member function
- All objects share the same function
- Static member functions can only access static member variables
#include <iostream> using namespace std; // Static member function class Person { public: // Static member function static void func() { c_A = 100; // c_B = 100; // Static member functions cannot access non static member variables cout << "static void func" << c_A << endl; } static int c_A; // Static member variable, class declaration int c_B; // Non static member variable }; int Person::c_A = 10; // Initialization outside class void test() { // visit Person p; p.func(); // Access by object Person::func(); // Access through class name:: is the domain operator } int main() { test(); system("pause"); return 0; }
Static functions also have access
3. C + + object model and this pointer
3.1 member variables and member functions are stored separately
In C + +, in class member variables and member functions are stored separately
Only non static member variables are objects of a class
#include <iostream> using namespace std; // Member variables and member functions are stored separately class Person { int c_A; // Non static member variable, object belonging to class static int c_B; // Static member variable, which does not belong to class object void fn() {}; // Non static member function, which does not belong to class object static void fn() {}; // Static member function, object that does not belong to class }; void test01() { Person p; /* The memory space occupied by empty objects is 1 C++ The compiler will also allocate a byte space to each empty object to distinguish the memory occupied by empty objects Each empty object should also have a unique memory address */ cout << sizeof(p) << endl; } int main() { test01(); system("pause"); return 0; }
3.2 this pointer
Each non static member function will only produce one function instance, that is, multiple objects of the same type will share a piece of code
C + + determines whether this piece of code is called by an object by providing a special object pointer and this pointer.
this pointer points to the object to which the called member function belongs
this pointer is a pointer implied in every non static member function
this pointer does not need to be defined and can be used directly
purpose
- When a formal parameter has the same name as a member variable, it can be distinguished by this pointer
- Return the object itself in the non static member function of the class. You can use return *this
#include <iostream> using namespace std; class Person { public: Person(int age) { this->c_age = age; // The this pointer points to the object to which the called member function belongs } int c_age; Person& addAge(Person &p) { // Person & a reference that returns a value. If a value is returned, a new object will be created this->c_age += p.c_age; return *this; // This refers to the pointer of the object calling the function, so * this refers to the ontology of the object } }; void test01() { Person p1(18); cout << "p1 Your age is" << p1.c_age << endl; } void test02() { Person p1(18); Person p2(19); // Chain programming idea p2.addAge(p1).addAge(p1); cout << "p2 Your age is" << p2.c_age << endl; } int main() { test01(); test02(); system("pause"); return 0; }
3.3 null pointer access member function
C + + hollow pointer can also call member functions, but pay attention to whether there is a useful this pointer
If this pointer is used, it needs to be judged to ensure the robustness of the code
#include <iostream> using namespace std; class Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { // The reason for the error is that the pointer passed in is NULL if (this == NULL) { return; } cout << "age=" << c_Age << endl; } int c_Age; }; void test01() { Person* p = NULL; p->showClassName(); //p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
3.4 const modifier member function
Constant function
- After adding const to the member function, we call this function a constant function
- Member properties cannot be modified within a constant function
- After the keyword mutable is added to the member attribute declaration, it can still be modified in the constant function
Constant object
- Add const before declaring the function to call the object a constant object
- Constant objects can only call constant functions
// Constant function class Person { public: // The essence of this pointer is a pointer constant, and the pointer cannot be modified void showPerson() const { // ->Equivalent to const Person * const this; Originally, it was Person * const this; // m_A = 100; // Will report an error this->m_B = 100; } int m_A; mutable int m_B; // For special variables, even in constant functions, you can modify this value and add the keyword mutable }; // Constant object void test() { const Person p; // It is a constant object // p.m_A = 100; // Modification not allowed p.m_B = 100; // m_B is a special value, which can also be modified under constant objects // Constant objects can only call constant functions, which cannot call ordinary member functions, because ordinary member functions can modify properties }
4. Friends
In the program, some private properties also want to be accessed by special functions or classes outside the class, so you need to use friend technology
The purpose of a friend is to let a function or class access private members in another class
The keyword of friend is: friend
Three implementations of friends
- Global function as friend
- Class as friend
- Member function as friend
4.1 global functions
// In the class, add an object declaration. At the same time, add friend at the beginning
// Global function as friend class Building { // goodGay global function is a good friend of Building. You can access private members in Building friend void goodGay(Building* building); public: Building() { m_Bedroom = "bedroom"; m_Sittingroom = "a living room"; } public: string m_Sittingroom; private: string m_Bedroom; }; // Global function void goodGay(Building* building) { cout << "Good friends visit" << building->m_Sittingroom << endl; cout << "Good friends visit" << building->m_Bedroom << endl; } void test01() { Building building; goodGay(&building);
Category 4.2
// Class as friend class Building { // Friends friend class GoodGay; public: Building(); public: string m_Sittingroom; private: string m_Bedroom; }; // Class write out member function Building::Building() { m_Bedroom = "bedroom"; m_Sittingroom = "a living room"; } // class class GoodGay { public: GoodGay(); void visitHouse(); Building* building; }; // Class write out member function GoodGay::GoodGay() { // Create a building object building = new Building; } void GoodGay::visitHouse() { cout << "A good friend is visiting" << building->m_Sittingroom << endl; cout << "A good friend is visiting" << building->m_Bedroom << endl; } void test() { GoodGay gg; gg.visitHouse(); }
4.3 member functions
class Building; // Class declaration class GoodGay { public: GoodGay(); void visit(); // Enables functions to access private members in Building void visit1(); // Make private members inaccessible to functions Building* building; }; class Building { friend void GoodGay::visit(); // Use domain operators public: Building(); string m_Sitttingroom; private: string m_Bedroom; }; // Implement member functions outside the class GoodGay::GoodGay() { building = new Building; } void GoodGay::visit() { cout << "Visiting" << building->m_Sitttingroom << endl; cout << "Visiting" << building->m_Bedroom << endl; } void GoodGay::visit1() { cout << "Visiting" << building->m_Sitttingroom << endl; // Cout < < visiting "< < building - > m_ Bedroom << endl; // report errors } Building::Building() { m_Sitttingroom = "a living room"; m_Bedroom = "bedroom"; } void test() { GoodGay gg; gg.visit(); cout << "---------"<< endl; gg.visit1(); }
5. Operator overloading
Operator overloading concept: redefine the existing operators and give them another function to adapt to different data types
5.1 plus operator
Function: realize the operation of adding two user-defined data types
// Plus operator overload class Person { public: // Member overloading Person operator+(Person& p) { Person temp; temp.m_A = this->m_A + p.m_A; temp.m_B = this->m_B + p.m_B; return temp; } int m_A; int m_B; }; // Global function overloading Person operator+(Person& p1, Person& p2) { Person temp; temp.m_A = p1.m_A + p2.m_A; temp.m_B = p1.m_B + p2.m_B; return temp; } void test() { Person p1; p1.m_A = 10; p1.m_B = 10; Person p2; p2.m_A = 10; p2.m_B = 10; // Essential call of member function // Person p3 = p1.operator+(p2); // Essential call of global function // Person p3 = operator+(p1, p2); Person p3 = p1 + p2; cout << "p3.m_A: " << p3.m_A << "\tp3.m_B: " << p3.m_B << endl; }
Operator overloading can also occur with function overloading
Person operator+(Person& p1, int num) { Person temp; temp.m_A = p1.m_A + num; temp.m_B = p1.m_B + num; return temp; } // Number addition
The operators of expressions with built-in data types cannot be changed
Do not abuse operator overloading
5.2 shift left operator
Function: you can output custom data types
// Overloaded operator shift left class Person { public: int m_A; int m_B; /* Overloading with member functions: p.operator < < (cout); - > Simplified function P < < cout; The < < operator will not be overloaded with member functions because cout cannot be realized on the left void operator<< (ostream& cout) { cout << "a:" << m_A << " b:" << m_B << endl; } */ }; void test() { Person p; p.m_A = 10; p.m_B = 10; cout << p << endl; } // You can only use global function overloading, ostream, which belongs to the standard output stream ostream& operator<< (ostream& cout, Person p) // Essence: operator < < (cout, P); - > Simplify cout < < p; { cout << "a:" << p.m_A << " b:" << p.m_B; return cout; // Chain programming should have return value }
Conclusion: overloading the shift left operator and cooperating with friends can output user-defined data types
5.3 increment operator
Function: realize your own integer data by overloading the increment operator
// Overload autoincrement operator // Custom integer class MyInt { friend ostream& operator<<(ostream& cout, MyInt i); // Friend access private element public: MyInt() { m_num = 0; } // Overloaded leading autoincrement operator MyInt& operator++() { ++m_num; // Auto increment operation return *this; } // Overloaded post increment operator MyInt operator++(int) // int represents a placeholder parameter, which is used to distinguish between pre increment and post increment. Be careful not to use references { // Record the results at that time first MyInt temp = *this; // Post self increasing m_num++; // Finally, return the result return temp; } private: int m_num; }; // Overload shift left operator ostream& operator<<(ostream& cout, MyInt i) { cout << i.m_num; return cout; } void test() { MyInt i; cout << ++i << "--" << i << endl; cout << "=====" << endl; cout << i++ << "--" << i << endl; }
5.4 assignment operator
The C + + compiler adds at least four functions to a class
- Default constructor (no parameters, empty function body)
- Default destructor (no parameters, empty function body)
- The default copy function copies the values of attributes
- The assignment operator operator =, copies the value of the attribute
If there is an attribute pointing to the heap area in the, the deep and shallow copy problem will also occur when performing the assignment operation
class Person { public: Person(int age) { m_Age = new int(age); // Open up data to heap } // Overload assignment operator Person& operator=(Person& p) { // The compiler provides a shallow copy of this - > M_ Age = p.m_ Age; // You should judge whether there are attributes in the heap area. If so, release them clean first, and then deep copy them if (this->m_Age) // Equivalent to if (this - > m_age! = null) { delete this->m_Age; // Delete data m_Age = NULL; } m_Age = new int(*p.m_Age); // Returns the object itself return *this; } int* m_Age; ~Person() { if (m_Age) // When m_ When age is not empty { delete m_Age; m_Age = NULL; } } }; void test() { Person p1(10); Person p2(20); p2 = p1; // Assignment operation, default to light copy cout << "p1 Your age is:" << *p1.m_Age << endl; cout << "p2 Your age is:" << *p2.m_Age << endl; }
5.5 relational operators
Function: overloads the relational operator, allowing two user-defined objects to compare
// Overloading relational operators class Person { public: Person(string name, int age); // Overload = = sign, others are similar bool operator==(Person& p); string m_Name; int m_Age; }; Person::Person(string name, int age) { this->m_Name = name; this->m_Age = age; } bool Person::operator==(Person& p) { if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) { return true; } else { return false; } } void test() { Person p1("Tom", 18); Person p2("Tom", 18); Person p3("Li Hua", 18); if (p1 == p2) { cout << "p1 == p2" << endl; } else { cout << "p1 != p2" << endl; } }
5.6 function call operator
- The function call operator () can also be overloaded
- Because the method used after overloading is very similar to the call of function, it is called imitation function
- Imitation function has no fixed writing method and is very flexible
class MyPrint { public: void operator()(string test) { cout << test << endl; } }; class Add { public: int operator()(int num1, int num2) { return num1 + num2; } }; void test() { MyPrint myPrint; myPrint("hello world"); // functor Add add; cout << "And are:" << add(1, 2) << endl; // Imitation function is very flexible and has no fixed writing method cout << "And are:" << Add()(2, 3) << endl; // Anonymous function object ` Add()` }
6. Inherit
Inheritance is one of the three characteristics of object-oriented
There are special relationships between some classes
For example: Animal - > cat - > Garfield
We found that when defining these classes, the lower level members not only have the commonalities of the upper level, but also have their own attributes
At this time, we can consider using inheritance technology to reduce duplicate code
6.1 basic grammar
Syntax: class subclass: inheritance method parent class
For example, in many websites, there are public headers, public bottoms, and even public left list columns
/* class Java { public: Java() // Use the constructor to output the content { cout << "Java Page: "< endl; header(); buttom(); left(); content(); cout << "=====" << endl; } void header() { cout << "Home page, open class, login, registration " << endl; } void buttom() { cout << "Help center, communication and cooperation, site map " << endl; } void left() { cout << "Java / Python / C++ ..." << endl; } void content() { cout << "Course on Java "< < endl; } }; class Python // Much of the content is the same as that of Java { public: Python() { cout << "Python Page: "< endl; header(); buttom(); left(); content(); cout << "=====" << endl; } void header() { cout << "Home page, open class, login, registration " << endl; } void buttom() { cout << "Help center, communication and cooperation, site map " << endl; } void left() { cout << "Java / Python / C++ ..." << endl; } void content() { cout << "Course on Python "< < endl; } }; // There are many function repetitions */ // Using inheritance ideas class PublicPage // Define public pages { public: void header() { cout << "Home page, open class, login, registration..." << endl; } void buttom() { cout << "Help center, communication and cooperation, station map..." << endl; } void left() { cout << "Java / Python / C++ ..." << endl; } }; class Java : public PublicPage { public: Java() { cout << "Java Page:" << endl; header(); buttom(); left(); content(); cout << "=====" << endl; } void content() { cout << "about Java Courses" << endl; } }; class Python : public PublicPage { public: Python() { cout << "Python Page:" << endl; header(); buttom(); left(); content(); cout << "=====" << endl; } void content() { cout << "about Python Courses" << endl; } }; void test() { Java java; Python python; }
Subclasses are also called derived classes
A parent class is also called a base class
6.2 mode of inheritance
Inheriting content that cannot access private permissions
There are three ways of inheritance
-
Public succession
- All public members in the base class are public attributes in the derived class
- All protected members in the base class are protected attributes in the derived class
- All private members in a base class cannot be used in a derived class
-
Protect inheritance
- All public members in the base class are protected in the derived class
- All protected members in the base class are protected attributes in the derived class
- All private members in a base class cannot be used in a derived class.
-
Private inheritance
- All public members in the base class are private attributes in the derived class;
- All protected members in the base class are private attributes in the derived class
- All private members in a base class cannot be used in a derived class
Inheritance method / base class member | public member | protected member | private member |
---|---|---|---|
public inheritance | public | protected | invisible |
protected inheritance | protected | protected | invisible |
private inheritance | private | private | invisible |
6.3 object model
Which members inherited from the parent class belong to the subclass objects?
// Object model in inheritance class Base { public: int m_A; private: int m_B; protected: int m_C; }; class Son : public Base { public: int m_D; }; void test() { cout << "size of son:" << sizeof(Son) << endl; // In the parent class, all non static member properties will be inherited by the child class // The private member attribute in the parent class is hidden by the compiler, so it is inaccessible, but it is inherited }
Use the developer command prompt tool to view the object model
- Jump drive letter
- Jump file path: cd specific path
- View command: cl /d1 reportSingleClassLayout class name file name
6.4 structure and destructional sequence
After the subclass inherits from the parent class, when the subclass object is created, the constructor of the parent class will also be called
class Base { public: Base() { cout << "Base Constructor for" << endl; } ~Base() { cout << "Base Destructor" << endl; } }; class Son : public Base { public: Son() { cout << "Son Constructor for" << endl; } ~Son() { cout << "Son Destructor" << endl; } }; void test() { Son son; // Dolls, white haired people give black haired people }
6.5 handling of members with the same name
When there are members with the same name in the subclass and parent class, how can you access the data with the same name in the subclass or parent class through the subclass object?
- Access subclass members with the same name: direct access
- Accessing a member with the same name as the parent class: scope is required
class Base { public: Base() { m_A = 100; } int m_A; void fn() { cout << "Base" << endl; } void fn(int a) { cout << a << endl; } }; class Son : public Base { public: Son() { m_A = 101; } int m_A; void fn() { cout << "Son" << endl; } }; void test() { Son s; cout << "s.m_A=" << s.m_A << endl; // Direct access cout << "Base.m_A=" << s.Base::m_A << endl; // Add scope s.fn(); s.Base::fn(); s.Base::fn(100); }
The method of calling a function with the same name is similar: add scope
If a member function with the same name as the parent class appears in the subclass, the member function with the same name in the subclass will hide all member functions with the same name in the parent class
If you want to access the member function with the same name hidden in the parent class, you need to add scope
6.6 processing of static members with the same name
Static members and non static members have the same name and are handled in the same way
- You can access the member with the same name in the subclass directly
- To access a member with the same name as the parent class, you need to add a scope
class Base { public: static int m_A; // Intra class declaration static void fn() { cout << "Base" << endl; } }; int Base::m_A = 100; // Class to initialize class Son : public Base { public: static int m_A; static void fn() { cout << "Son" << endl; } }; int Son::m_A = 101; void test() { cout << "Access data by class name" << endl; Son s; cout << "s.m_A=" << s.m_A << endl; cout << "Base.m_A=" << s.Base::m_A << endl; cout << "Access data by class name" << endl; cout << "Son.m_A=" << Son::m_A << endl; cout << "Base.m_A=" << Son::Base::m_A << endl; // The first pair of colons represents accessing the scope through the class name, and the second pair of colons represents accessing the scope under the parent class }
Function calls are similar
6.7 multi inheritance syntax
C + + allows a class to inherit multiple classes
Syntax: class subclass: inheritance method parent class 1, inheritance method parent class 2···
Multiple inheritance may cause members with the same name to appear in the parent class, which needs to be distinguished by scope
Multi inheritance is not recommended for C + + actual development
6.8 diamond inheritance
problem
- When B inherits the data of A and C also inherits the data of A, ambiguity will occur when D uses the data
- D inherits two data. In fact, we know that we only need to inherit one data
class A { public: int m_Age; }; /* Using virtual inheritance to solve the problem of diamond inheritance Before inheritance, add the keyword virtual to become virtual inheritance A Classes are called virtual base classes */ class B : virtual public A{}; class C : virtual public A{}; class D : public B, public C{}; void test() { D d; d.B::m_Age = 18; d.C::m_Age = 28; // When diamond inheritance occurs, the two parent classes have the same data and need to be distinguished cout << "B.m_Age = " << d.B::m_Age << endl; cout << "C.m_Age = " << d.C::m_Age << endl; // This data only needs one data. Diamond inheritance leads to two data, which is a waste of resources }
Using virtual inheritance to solve the problem of diamond inheritance
Before inheritance, add the keyword virtual to become virtual inheritance
Class A is called a virtual base class
7. Polymorphism
7.1 basic concepts
Polymorphism is one of the three characteristics of C + + object-oriented
Polymorphisms fall into two categories
- Static polymorphism: [function overload] (#3, function overload) and [operator overload] (#5, operator overload) belong to static polymorphism and reuse function names
- Dynamic polymorphism: derived classes and virtual functions implement runtime polymorphism
The difference between static polymorphism and dynamic polymorphism
- Statically polymorphic function address early binding - function address at compilation stage
- Dynamic polymorphic function address late binding - determine the function address at the run-time
class A { public: virtual void speak() // Virtual function, which can realize late address binding { cout << "A is speaking" << endl; } }; class B : public A { public: void speak() { cout << "B is speaking" << endl; } }; // Execute speaking function void doSpeak(A& a) // A& a = b; { a.speak(); // If virtual is not added, the address is bound early and the function address is determined at the compilation stage // If you want to execute b.speak(); Binding is required in the running phase, and the address is bound late } void test() { B b; doSpeak(b); }
Rewrite function: the return value type, function name and parameter list of the function are exactly the same
Dynamic condition satisfaction
- There is an inheritance relationship
- Subclass overrides the virtual function of the parent class, and the subclass override function can not be a virtual function
Dynamic polymorphic use
- The parent class pointer or reference executes the child class object
Polymorphic advantage
- Clear code organization
- Strong readability
- It is conducive to the expansion and maintenance in the early and later stages
7.2 case - calculator
// If there is an extension function, the opening and closing principle should be realized: open the extension and close the modification class AbstarctCalc // abstract class { public: virtual int getResult() // virtual function { return 0; } int m_A; int m_B; }; class Add : public AbstarctCalc // addition { public: int getResult() { return m_A + m_B; } }; class Sub : public AbstarctCalc { public: int getResult() { return m_A - m_B; } }; void test() { // Polymorphic service conditions // A parent class pointer or reference points to a child class object AbstarctCalc* abc = new Add; abc->m_A = 10; abc->m_B = 20; cout << abc->m_A << " + " << abc->m_B << " = " << abc->getResult() << endl; // Execute subclass object delete abc; // Destroy data abc = new Sub; abc->m_A = 10; abc->m_B = 20; cout << abc->m_A << " - " << abc->m_B << " = " << abc->getResult() << endl; }
7.3 pure virtual functions and abstract classes
In polymorphism, the implementation of virtual functions in the parent class is meaningless, which is mainly the content rewritten by calling subclasses
Therefore, virtual functions can be changed to pure virtual functions
Pure virtual function syntax: virtual return value type function name (parameter list) = 0
When there are pure virtual functions in a class, this class is also called an abstract class
Characteristics of abstract classes
- Cannot implement instantiated object
- Subclasses must override pure virtual functions in abstract classes, otherwise they also belong to abstract classes
class Base { public: virtual void func() = 0; }; class Son : public Base { public: void func() { cout << "Son" << endl; } }; void test(Base& b) // Reference parent class pointer { b.func(); } void test() { Son s; test(s); }
7.4 virtual deconstruction and pure virtual deconstruction
When polymorphism is used, if an attribute in a subclass is opened to the heap, the parent class pointer cannot call the destructor code of the subclass when it is released
Solution: change the destructor in the parent class to virtual destructor or pure virtual destructor
Analysis of virtual and pure commonness
- You can solve the problem of releasing subclass objects from parent class pointers
- All need specific function implementation
The difference between virtual destruct and pure virtual destruct
- If it is a pure virtual destructor, this class belongs to an abstract class and cannot instantiate an object
Virtual destructor syntax: virtual ~ class name () {}
Pure virtual destructor syntax: class interior: virtual ~ class name () = 0| Out of class: Class Name:: ~ class name () {}
// Virtual destruct and pure virtual destruct class A { public: A() { cout << "A()" << endl; } virtual void speak() = 0; virtual ~A() { cout << "~A()" << endl; } // Pure virtual destruct virtual ~A() = 0; }; // A::~A() {} / / pure virtual destructor requires function implementation class C : public A { public: C(string name) { cout << "C()" << endl; m_name = new string(name); // Open up data to heap } void speak() { cout << *m_name << " is speaking" << endl; } string* m_name; // This destructor is not called when virtual is not added ~C() { if (m_name) { cout << "~C()" << endl; delete m_name; m_name = NULL; } } }; void test() { A* a = new C("Tom"); a->speak(); // When the parent class pointer is destructed, it will not call the destructor in the subclass, resulting in a waste of resources if the subclass has heap attributes delete a; }
Virtual destructors or pure virtual destructors are used to solve the problem of releasing subclass objects through parent class pointers
If no data in the subclass is opened to the heap area, it can not be written as virtual destruct or pure virtual destruct
Classes with pure virtual destructors are also abstract classes
5, File operation
The data generated when the program runs belongs to temporary data. Once the program runs, it will be released
Data can be stored persistently through files
File operations in C + + need to include header files < fstream >
- Text file: the file is stored in the computer in the form of ASCII code of text
- Binary file: the file is stored in the computer in the binary form of text, which is generally not directly readable by users
Operation documents are divided into three categories
- ofstream: write operation
- ifstream: read operation
- fstream: read / write operation
1. Text file
1.1 writing documents
1.1.1 steps
-
Include header file
-
#include <fstream>
-
-
Create flow object
-
ofstream ofs;
-
-
Open file
-
ofs.open("File path", Open mode);
-
-
Write data
-
ofs << "Data written";
-
-
Close file
-
ofs.close();
-
1.1.2 file opening method
Pattern mark | Applicable object | effect |
---|---|---|
ios::in | ifstream fstream | Open the file for reading data. If the file does not exist, there is an error opening it. |
ios::out | ofstream fstream | Open file for writing data. If the file does not exist, create a new one; If the file already exists, the original contents will be cleared when it is opened. |
ios::app | ofstream fstream | Open a file to add data to its tail. If the file does not exist, create a new one. |
ios::ate | ifstream | Open an existing file and point the file read pointer to the end of the file (the concept of read-write refers will be explained later). If the file does not exist, there is an error opening it. |
ios:: trunc | ofstream | When the file is opened, all the data stored inside will be emptied. When used alone, it is the same as ios::out. |
ios::binary | ifstream ofstream fstream | Open the file in binary mode. If this mode is not specified, it is opened in text mode. |
ios::in | ios::out | fstream | Open an existing file to read its contents or write data to it. When the file is first opened, the original content remains unchanged. If the file does not exist, there is an error opening it. |
ios::in | ios::out | ofstream | Open files to which data can be written. When the file is first opened, the original content remains unchanged. If the file does not exist, there is an error opening it. |
ios::in | ios::out | ios::trunc | fstream | When you open a file, you can read its contents or write data to it. If the file already exists, clear the original content when opening it; If the file does not exist, create a new one. |
The file opening method can be used with |
1.2 document reading
The steps of reading and writing files are similar, but there are relatively many reading methods
-
Include header file
-
#include <fstream>
-
-
Create flow object
-
ifstream ifs;
-
-
Open file
-
ifs.open("File path", Open mode); if (!ifs.is_open()) { cout << File open failed << endl; return; } // ifs.is_open() failed to judge whether the file is opened
-
-
Read data
-
// Four ways to read // First kind char buf[1024] = { 0 }; // Initialize character array while (ifs >> buf) { cout << buf << endl; } // Second char buf[1024] = { 0 }; // Initialize character array while (ifs.getline(buf, sizeof(buf))) { coutt << buf << endl; } // Third string buf; while (getline(ifs, buf)) { cout << buf << endl; } // Fourth (not recommended) char c; while (c = ifs.get() != EOF) // End of EOF file { cout << c; }
-
-
Close file
-
ifs.close();
-
2. Binary file
Read and write files in binary mode
The opening method is ios::binary
2.1 writing documents
Writing files in binary mode mainly uses the stream object to call the member function write
Syntax: ostream & write (const char * buffer, int len);
parameter
- buffer: character pointer pointing to a storage space in memory
- len: number of bytes read and written
class Person { public: char m_Name[64]; int m_Age; }; // Include header file // #include <fstream> // Create flow object ofstream ofs; // Open file ofs.open("Person.txt", ios::binary | ios::out); // You can also: ofstream ofs("Person.txt", ios::binary | ios::out); // Write file Person p = { "Zhang San", 18 }; ofs.write((const char*)&p, sizeof(Person)); // Close file ofs.close();
2.2 reading documents
Binary file reading mainly uses the stream object to call the member function read
Syntax: istream & read (char * buffer, int len)
parameter
- buffer: character pointer pointing to a storage space in memory
- len: number of bytes read and written
class Person { public: char m_Name[64]; int m_Age; }; // Include header file #include < fstream > // Create flow object ifstream ifs; // Open the file and judge whether the file is opened successfully ifs.open("Person.txt", ios::in | ios::binary); if (!ifs.is_open()) { cout << "File open failed" << endl; return; } // read file Person p; ifs.read((char*)&p, sizeof(Person)); cout << "full name:" << p.m_Name << " Age:" << p.m_Age << endl; // Close file ifs.close();