4.2 initialization and cleaning of objects
- In life, the electronic products we buy will basically have factory settings. One day, we will delete some of our own information data when we are not in use to ensure security
- The object-oriented in C + + comes from life. Each object will also have initial settings and settings for cleaning data before object destruction.
4.2.1 constructors and destructors
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 cleaning of objects are what the compiler forces us to do, so if we don't provide construction and destruction, the compiler will provide
The constructor and destructor provided by the compiler are empty implementations.
- Constructor: it is mainly used to assign values to the member properties of the object when creating the object. The constructor is automatically called by the compiler without manual call.
- Destructor: it is mainly used to automatically call and perform some cleaning 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, so overloading can occur
- When the program calls the object, it will automatically call the construct without manual call, and it will only be called once
Destructor syntax: ~ class name () {}
- Destructor, no return value, no write void
- The function name is the same as the class name, and the symbol is added before the name~
- Destructors cannot have parameters, so overloading cannot occur
- The program will automatically call the destructor before the object is destroyed, without manual call, and will only call it once
#include <iostream> using namespace std; // Object initialization and cleanup // 1. Constructor to perform the initial operation class Person { public: // 1. Constructor // No return value, no need to write void // The function name is the same as the class name // Constructors can have parameters and can be overloaded // When creating an object, the constructor will be called automatically, and it will be called once Person() { cout << "Person Call to constructor" << endl; } // 2. The destructor performs a cleanup operation // void is not written if there is no return value // The function name is the same as the class name, and the name is preceded by~ // Destructors cannot have parameters and cannot be overloaded // The destructor will be called automatically and only once before the object is destroyed ~Person() { cout << "Person Destructor call for" << endl; } }; // Construction and deconstruction are necessary implementations. If we don't provide them ourselves, the compiler will provide a construction and Deconstruction of an empty implementation void test01() { Person p; // For the data on the stack, release the object after test01 is executed } int main() { test01(); //Person p; system("pause"); return 0; }
4.2.2 classification and calling of constructors
Two classification methods:
According to parameters, it can be divided into parametric structure and nonparametric structure
By type, it can be divided into ordinary structure and copy structure
Three call modes:
bracketing
Display method
Implicit transformation method
Example:
#include <iostream> using namespace std; // 1. Classification and call of constructor // classification // Parameterless construction (default construction) and parameterless construction are classified according to parameters // Construct a common copy constructor by type class Person { public: // Constructor Person() { cout << "Person Call to parameterless constructor" << endl; } Person(int a) { age = a; cout << "Person Call with parameter constructor" << endl; } // copy constructor Person(const Person& p) { // Copy all the attributes of the incoming person to me age = p.age; cout << "Person Call to copy constructor" << endl; } ~Person() { cout << "Person Call to destructor" << endl; } int age; }; // call void tste01() { // 1. Bracket hair //Person p1; // Call to default constructor //Person p2(10); // Parameterized constructor //Person p3(p2); // copy constructor // matters needing attention // When calling the default constructor, do not add () // Because of the following line of code, the compiler will consider it as a declaration of a function and will not consider it as creating an object // Person p4(); //Cout < < P2's age is: < < P2 age << endl; //Cout < < P3's age is: < < P3 age << endl; // 2. Display method //Person p1; //Person p2 = Person(10); // Parametric structure //Person p3 = Person(p2); // copying functions //Person(10); // Anonymous object features: after the execution of the current line, the system will immediately recycle the anonymous object //cout << "aaaa" << endl; // Note 2 // Do not initialize anonymous objects with copy constructors // The compiler will assume that Person (p3) === Person p3; Object declaration Person(p3); // 3. Implicit transformation method Person p4 = 10; // P4 = person (10) relative to the person written; Parametric structure Person p5 = p4; // copy construction } int main() { tste01(); system("pause"); return 0; }
4.2.3 call timing of copy constructor
There are three situations in C + + when copying constructor calls
- Initialize a new object with an already created object
- Values are passed to function parameters
- Returns a local object as a value
Example:
#include <iostream> using namespace std; // Copy constructor call timing class Person { public: Person() { cout << "Person Default constructor call" << endl; } Person(int age) { m_Age = age; cout << "Person Parameterized constructor call" << endl; } Person(const Person& p) { m_Age = p.m_Age; cout << "Person Copy constructor call" << endl; } ~Person() { cout << "Person Destructor call" << endl; } int m_Age; }; // 1. Initialize a new object with an already created object void test01() { Person p1(20); Person p2(p1); cout << "p2 Your age is:" << p2.m_Age << endl; } // 2. Value is passed to the function parameter value void doWork(Person p) { } void test02() { Person p; doWork(p); } // 3. Returns a local object by value Person doWork2() { Person p1; cout << (int*)&p1 << endl; return p1; } void test03() { Person p = doWork2(); cout << (int*)&p << endl; } int main() { // test01(); // test02(); test03(); system("pause"); return 0; }
4.2.4 constructor calling rules
By default, the c + + compiler adds at least three functions to a class
1. Default constructor (no parameters, empty function body)
2. Default destructor (no parameters, empty function body)
3. The default copy constructor copies the value of the attribute
Constructor calling rules are as follows:
-
If the user defines a parameterized constructor, c + + will no longer provide a default parameterless construct, but will provide a default copy construct
-
If you define a copy constructor, c + + will not provide another constructor
Example:
#include <iostream> using namespace std; // Call to constructor // 1. Create a class, and the C + + compiler will add at least 3 functions to each class // Default construct (empty Implementation) // Destructor (empty Implementation) // Copy construction (value copy) // 2. If we write a parameterized constructor, the compiler will no longer provide the default constructor, but still provide the copy constructor // If we write a copy constructor, the compiler will no longer provide other ordinary constructors class Person { public: //Person() //{ // Cout < < default constructor call of person < < endl; //} //~Person() //{ // Cout < < destructor call of person < < endl; //} //Person(int age) //{ // m_Age = age; // Cout < < person's parameterized constructor call < < endl; //} Person(const Person& p) { m_Age = p.m_Age; cout << "Person Copy constructor call" << endl; } int m_Age; }; //void test01() //{ // Person p; // p.m_Age = 18; // // Person p2(p); // // Cout < < P2's age is: < < P2 m_ Age << endl; //} void test02() { Person p; //Person p2(p); //Cout < < P2's age is: < < P2 m_ Age << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
4.2.5 deep copy and shallow copy
Deep and shallow copy is not only a classic interview question, but also a common pit
Shallow copy: a simple assignment copy operation
Deep copy: re apply for space in the heap area for copy operation
Example:
#include <iostream> using namespace std; // Deep and shallow copies class Person { public: Person() { cout << "Person Default constructor call for" << endl; } Person(int age, int height) { m_Age = age; m_Height = new int(height); cout << "Person Parameterized constructor call" << endl; } // Implement the copy constructor to solve the problems caused by shallow copy Person(const Person& p) { cout << "Person Copy constructor call" << endl; m_Age = p.m_Age; // m_Height = p.m_Height; // The compiler's default implementation is this line of code // Deep copy operation m_Height = new int(*p.m_Height); } ~Person() { // Destruct the code and release the heap development data if (m_Height != NULL) { delete m_Height; m_Height = NULL; } cout << "Person Destructor call for" << endl; } int m_Age; int* m_Height; }; void test01() { Person p1(18, 160); cout << "p1 Your age is:" << p1.m_Age << " Height:" << *p1.m_Height << endl; Person p2(p1); cout << "p1 Your age is:" << p2.m_Age << " Height:" << *p2.m_Height << endl; } int main() { test01(); system("pause"); return 0; }
Summary: if the attribute is opened in the heap area, you must provide your own copy constructor to prevent problems caused by shallow copy
4.2.6 initialization list
effect:
C + + provides initialization list syntax to initialize attributes
Syntax: constructor (): Property 1 (value 1), property 2 (value 2) {}
Example:
#include <iostream> using namespace std; // Initialization list class Person { public: // Traditional initialization operation //Person(int a, int b, int c) //{ // m_A = a; // m_B = b; // m_C = c; //} // Initialization list initialization properties Person(int a, int b, int c) : m_A(a), m_B(b), m_C(c) { } int m_A; int m_B; int m_C; }; void test01() { // Person p(10, 20, 30); Person p(30, 20, 10); cout << "m_A: " << p.m_A << endl; cout << "m_B: " << p.m_B << endl; cout << "m_C: " << p.m_C << endl; } int main() { test01(); system("pause"); return 0; }
4.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
For example:
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 order of construction and Deconstruction of A and B?
Example:
#include <iostream> using namespace std; // Class objects as class members // Mobile phone class class Phone { public: Phone(string p) { m_PName = p; cout << "Phone constructor call " << endl; } ~Phone() { cout << "Phone Destructor call" << endl; } // Name of mobile phone brand string m_PName; }; class Person { public: // Phone m_Phome = pName; // Implicit transformation method Person(string name, string pName) : m_Name(name), m_Phone(pName) { cout << "Person constructor call " << endl; } ~Person() { cout << "Person Destructor call" << endl; } // full name string m_Name; // mobile phone Phone m_Phone; }; // When other class objects are members of this class, class objects are constructed first, and then themselves. The deconstruction order is opposite void test01() { Person p("Zhang San", "Apple MAX"); cout << p.m_Name << "Take:" << p.m_Phone.m_PName << endl; } int main() { test01(); system("pause"); return 0; }
4.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
- Inner class declaration, outer class initialization
- Static member function
- All objects share the same function
- Static member functions can only access static member variables
Example 1: static member variables
#include <iostream> using namespace std; // Static member class Person { public: // 1. All objects share the same data // 2. Memory is allocated at compile time // 3. Inner class declaration, outer class initialization static int m_A; // Static member variables also have access rights private: static int m_B; }; int Person::m_A = 100; int Person::m_B = 200; void test01() { Person p; cout << p.m_A << endl; Person p2; p.m_A = 200; // 200 cout << p.m_A << endl; } void test02() { // Static member variables do not belong to an object, and all objects share the same data // Therefore, static member variables can be accessed in two ways // 1. Access through objects //Person p; //cout << p.m_A << endl; // 2. Access by class name cout << Person::m_A << endl; // cout << Person::m_ B << endl; // Private static member variable not accessible outside class } int main() { // test01(); test02(); system("pause"); return 0; }
Example 2: static member function
#include <iostream> using namespace std; // Static member function // All objects share a function // Static functions can only access static members class Person { public: // Static member function static void func() { m_A = 100; // Static member functions can access static member variables // m_B = 200; // Static member functions cannot access non static member variables, and it is impossible to distinguish which object is m_B attribute cout << "static void func call" << endl; } static int m_A; // Static member variable int m_B; // Non static member variable private: static void func2() { cout << "static void func2 call" << endl; } }; int Person::m_A = 0; // There are two ways to access void test01() { // 1. Access by object Person p; p.func(); // 2. Access by class name Person::func(); // Person::func2(); // Private static member function not accessible outside class } int main() { test01(); system("pause"); return 0; }