Object Features
Constructors and destructors
Initialization and cleaning of objects are also two very important security issues.
An object or variable has no initial state, and the consequences of its use are unknown.
The same thing that fails to clean up an object or variable in time will also cause certain security problems.
- Constructor: The main function is to assign values to the object's member attributes when creating an object. The constructor is automatically called by the compiler and does not require manual call.
- Destructor: The main function is that the system automatically calls the object before it is destroyed and some cleaning work is performed
Constructor syntax: class name(){}
1. Constructor, no return value and no void is written
2. The function name is the same as the class name
3. The constructor can have parameters, so overloading can occur
4. The program will automatically call the construct when calling the object, without manual call, and it will only be called once.
Destructor syntax: ~Class name(){}
1. Destructor, no return value and no void is written
2. The function name is the same as the class name, and the name is added with a symbol~
3. The destructor cannot have parameters, so overloading cannot occur.
4. The program will automatically call destructors before calling the object, without manual calls, and will only be called once.
#include<iostream> using namespace std; //Object initialization and cleaning//1.Constructor implements initialization operationclass Person { public: //1Constructor //No return value is required //The function name is the same as the class name //The constructor can have parameters and overloading can occur //When creating an object, the constructor will be called automatically and only once Person() { cout<< "Call of Person constructor" << endl; } //2. Destructor implements cleaning operation //No return value is not written void //The function name is the same as the class name. Add one before the name ~ //The destructor cannot have parameters and overload cannot occur //The destructor will be automatically called before the object is destroyed and will only be called once. ~Person() { cout << "Call of Person destructor" << endl; } }; //Construction and destruction are necessary implementations. If we do not provide them ourselves, the compiler will provide an empty implementation of the construction and destruction.void test01() { Person p;// After the data on the stack is executed, release this object after test01 is executed.} int main() { test01(); system("pause"); return 0; }
Function classification and call
Classification and calls of constructors
Two classification methods:
- According to parameters, it is divided into: parameter structure and parameter structure
- By type: normal construction and copy construction
Three ways of calling:
- Bracketing method
- Display method
- Implicit conversion method
#include<iostream> using namespace std; //Classification and call of constructor//Classification//Classification by parameter: Non-parameter structure (default construction) and parameterized structure//Classification by type Normal construction Copy constructionclass Person { public: //Constructor Person() { cout << "Person's parameterless constructor call" << endl; } Person(int a) { age = a; cout << "Person's parameter constructor call" << endl; } //Copy constructor Person(const Person &p) { //Copy all attributes of the person being passed on to "me" age = ; cout << "Person's copy constructor call" << endl; } ~Person() { cout << "Person's destructor call" << endl; } int age; }; //Callvoid test01() { //1. Bracketing method //Person p1;//Default function call //Person p2(10);//Argument constructor //Person p3(p2);//Copy constructor //Precautions //Do not add () when calling the default constructor //Because of the following line of code, the compiler will consider it to be a declaration of a function and will not consider it to be creating an object //Person p1(); /*cout << "P2's age:" << << endl; cout << "P3's age:" << << endl;*/ //2. Display method //Person p1; //Person p2 = Person(10);//Article structure //Person p3 = Person(p3);//Copy construction //Person(10);//Anonymous object Features: After the execution of the current line is completed, the system will immediately recycle the anonymous object. // // Note 2 // Don't use copy constructors to initialize anonymous objects. The compiler will think that Person(p3) === Person p3; object declaration //Person(p3); //3. Implicit conversion method Person p4 = 10;//Equivalent to writing Person p4 = Person(10); Parameter structure Person p5 = p4;//Copy construction} int main() { test01(); system("pause"); return 0; }
Copy constructor call timing
There are usually three situations when copy constructor calls
1. Initialize a new object using a created object
2. The way of value transfer is passed to function parameters
3. Return local object as value
#include<iostream> using namespace std; //Call time of copy constructor//1. Initialize a new object using an object that has been created.//2. The method of value transfer to function parameters to pass values//3. Value method returns local objectclass Person { public: Person() { cout << "Person's default constructor call" << endl; } Person(int age) { cout << "Person's parameter constructor call" << endl; m_Age = age; } Person(const Person &p) { cout << "Person's copy constructor call" << endl; m_Age = p.m_Age; } ~Person() { cout << "Person destructor call" << endl; } int m_Age; }; //Call time of copy constructor//1. Initialize a new object using an object that has been created.void test01() { Person p1(20); Person p2(p1); cout << "The age of p2 is:" << p2.m_Age << endl; } //2. The method of value transfer to function parameters to pass valuesvoid doWork(Person p) { } void test02() { Person p; doWork(p); } //3. Value method returns local objectPerson doWork2() { Person p1; return p1; } void test03() { Person p = doWork2(); } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
Constructor call rules
By default, the c++ compiler adds at least 3 functions to one class
1. Default constructor (no arguments, function body is empty)
2. Default destructor (no arguments, function body is empty)
3. The default copy constructor is used to copy the attribute value
The constructor call rules are as follows
If the user defines a parameter constructor, C++ no longer provides a default parameter-free construct, but it provides a default copy construct.
If the user defines the copy constructor, c++ no longer provides other constructors.
#include<iostream> using namespace std; //Constructor calling rules//1. Created a class, the c++ compiler will add at least three functions to each class//Default construction (empty implementation)//Destructor (empty implementation)//Copy construct (value copy)//2. If we write a parameter constructor, the compiler will no longer provide the default construct, but will still provide the copy construct.//If we write a copy constructor, the compiler will no longer provide other constructorsclass Person { public: /*Person() { cout << "Person's default constructor call" << endl; }*/ /*Person(int age) { cout << "Person's parameter constructor call" << endl; m_Age = age; }*/ Person(const Person& p) { cout << "Person's copy constructor call" << endl; m_Age = p.m_Age; } ~Person() { cout << "Person's destructor call" << endl; } int m_Age; }; //void test01() { // Person p; // p.m_Age = 18; // Person p2(p); // cout << "The age of p2 is: " << p2.m_Age << endl;//} void test02() { Person p(28); Person p2(p); cout << "The age of p2 is:" << p2.m_Age << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
Deep and shallow copy
- Shallow copy: simple assignment copy operation
- Deep copy: Re-apply for space in the heap area and perform copy operation
#include<iostream> using namespace std; //Deep copy and shallow copyclass Person { public: Person() { cout << "Person's default constructor call" << endl; } Person(int age,int height) { m_Age = age; m_Height = new int(height); cout << "Person's parameter constructor call" << endl; } Person(const Person &p) { cout << "Person copy constructor call" << endl; m_Age = p.m_Age; //m_Height = p.m_Height; The default implementation of the compiler is this line of code //Deep copy operation //If it is not conducive to deep copy creating memory in the heap area, it will lead to repeated release of the heap area caused by shallow copy. m_Height = new int(*p.m_Height); } ~Person() { //Destruct the heap area and release the heap area to open data for free operation if (m_Height != NULL) { delete m_Height; m_Height = NULL; //The problem caused by shallow copy is the repeated release of problems in the heap area //The problem of shallow copy should be solved by using deep copy } cout << "Person's destructor call" << endl; } int m_Age;//age int* m_Height;//height}; void test01() { Person p1(18,160); cout << "The age of p1 is:" << p1.m_Age <<"Height is:"<<*p1.m_Height << endl; Person p2(p1); cout << "The age of p2 is:" << p2.m_Age <<"Height is:"<<*p2.m_Height << endl; } int main() { test01(); system("pause"); return 0; }
If the attribute is opened in the heap area, you must provide your own copy constructor to prevent problems caused by shallow copy.
Initialization list
effect:C++ provides initialization list syntax to initialize attributes
grammar:Constructor(): Property 1 (value 1), Property 2 (value 2)...{}
#include<iostream> using namespace std; //Initialization listclass Person { public: //Traditional initialization operation /*Person(int a, int b, int c) { m_A = a; m_B = b; m_C = c; }*/ //Initialize list initialization attribute 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; }
Class objects as class variables
A member in a c++ class can be an object of another class, and we call that member an object member
For example:
class A{}
class B
{
A a;
}
In Class B, object A is used as a member, and A is an object member
#include<iostream> using namespace std; //Class object as class member//Mobile phoneclass Phone { public: Phone(string pName) { cout << "Phone's constructor call" << endl; m_PName = pName; } ~Phone() { cout << "Phone's destructor call" << endl; } //Mobile phone brand name string m_PName; }; //Humanclass Person { public: //Phone m_Phone = pName Implicit conversion method Person(string name, string pName):m_Name(name),m_Phone(pName) { cout << "Person's constructor call" << endl; } ~Person() { cout << "Person's destructor call" << endl; } //Name string m_Name; //cell phone Phone m_Phone; }; //When other class objects are members of this class, when constructing, first construct the class objects and then construct themselves. The order of destruction is the opposite of the construction.void test01() { Person p("Zhang San","apple"); cout << p.m_Name << "Hold" << p.m_Phone.m_PName << endl; } int main() { test01(); system("pause"); return 0; }
Static members
Static members are the keyword static before member variables and member functions, which are called static members.
Static members are divided into:
Static member variables
All objects share a copy of data
Allocate memory during compilation phase
In-class declaration, out-of-class initialization
Static member functions
All objects share the same function
Static member functions can only access static member variables.
#include<iostream> using namespace std; // Static member functions//All objects share the same function// Static member functions can only access static member variablesclass Person { public: // Static member functions 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 cannot distinguish which m_B it is cout << "Call of static void func" << endl; } static int m_A;// Static member variable int m_B;//Non-static member variable // Static member functions also have access permissionsprivate: static void func2() { cout << "Call of static void func2" << endl; } }; int Person::m_A = 0; //There are two ways to accessvoid test01() { //1. Access through objects Person p; (); //2. Access through class name Person::func(); //Person::func2(); Unable to access private static member functions outside the class} int main() { test01(); system("pause"); return 0; }
Member variables and member functions are stored separately
In c++, class member variables and member functions are stored separately in class
Only non-static member variables belong to objects of the class
#include<iostream> using namespace std; //Member variables and member functions are stored separatelyclass Person { int m_A;//Non-static member variables on objects belonging to the class static int m_B;// Static member variables on objects that do not belong to the class void func() {}//Non-static member functions on objects that do not belong to the class static void func2() {}// Static member function on objects that do not belong to the class}; int Person::m_B = 0; void test01() { Person p; //The memory space occupied by an empty object is: 1 //The c++ compiler will also allocate a byte space to each empty object, in order to distinguish the memory location of empty objects. //Each empty object should also have a unique memory address cout << "size of p = "<<sizeof(p) << endl; } void test02() { Person p; cout << "size of p = " << sizeof(p) << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
The purpose of this pointer
- This pointer points to the object to which the called member function belongs.
- This pointer is a pointer that implies every non-static member function.
- This pointer does not need to be defined, just use it directly
Uses of this pointer:
When the formal parameter and member variable have the same name, this pointer can be used to distinguish it.
Return the object itself in a non-static member function of the class, you can use return * this to return
#include<iostream> using namespace std; class Person { public: Person(int age) { //This pointer points to the object to which the called member function belongs this->age = age; } int age; Person PersonAddAge(Person &p) { this->age += ; //This pointer to p2, and *this points to the object itself of p2 return *this; } }; //1. Resolve name conflictvoid test01() { Person p1(18); cout << "The age of p1 is:" << << endl; } //2. Return the object itself with *thisvoid test02() { Person p1(10); Person p2(10); //Chain programming idea (p1).PersonAddAge(p1).PersonAddAge(p1); cout << "The age of p2 is:" << << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
null pointer accessing member
C++ hollow pointer can also call member functions, but you should also pay attention to whether this pointer is used.
If this pointer is used, it is necessary to judge and ensure the robustness of the code.
#include<iostream> using namespace std; //Null pointer calls member functionclass Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { //The reason for the error is that the incoming pointer is NULL if (this == NULL) { return; } cout << "age = " <<this-> m_Age << endl; } int m_Age; }; void test01() { Person* p = NULL; //p->showClassName(); p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
Const modify member functions
Normal functions
After adding const to member functions, we call this function a constant function
Member properties cannot be modified in the function
After adding the keyword mutable when declaring member attributes, it can still be modified in normal functions.
Common objects:
Add const before declaring the object to call it a normal object
A normal object can only call a normal function.
#include<iostream> using namespace std; //Null pointer calls member functionclass Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { //The reason for the error is that the incoming pointer is NULL if (this == NULL) { return; } cout << "age = " <<this-> m_Age << endl; } int m_Age; }; void test01() { Person* p = NULL; //p->showClassName(); p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
Friends
The purpose of a friend is to allow a function or class to access private members in another class.
Friend keyword is friend
Three implementations of Youyuan:
- Global functions are used as friends
- Become a friend
- Member functions are friends
Global functions are used as friends
#include<iostream> using namespace std; #include<string> //Buildingsclass Building { //The goodGay global function is a good friend of Building and can access private members in Building friend void goodGay(Building* building); public: Building() { m_SittingRoom = "living room"; m_BedRoom = "bedroom"; } public: string m_SittingRoom;//living roomprivate: string m_BedRoom;//bedroom}; //Global Functionvoid goodGay(Building *building) { cout << "Good gay friend global function is being accessed:" << building->m_SittingRoom << endl; cout << "Good gay friend global function is being accessed:"<<building->m_BedRoom << endl; } void test01() { Building building; goodGay(&building); } int main() { test01(); system("pause"); return 0; }
Become a friend
#include<iostream> using namespace std; #include<string> //Class to be friendsclass Building; class GoodGay { public: GoodGay(); void visit();// Visit the function to access properties in Building Building* building; }; class Building { //GoodGay class is a good friend and can access private members of this class friend class GoodGay; public: Building(); public: string m_SittiingRoom;//living roomprivate: string m_BedRoom;//bedroom}; //Writing member functions outside the classBuilding::Building() { m_SittiingRoom = "living room"; m_BedRoom = "bedroom"; } GoodGay::GoodGay() { //Create a building object building = new Building; } void GoodGay::visit() { cout << "Good friends are visiting:"<<building->m_SittiingRoom << endl; cout << "Good friends are visiting:" << building->m_BedRoom << endl; } void test01() { GoodGay gg; (); } int main() { test01(); system("pause"); return 0; }
Member functions are friends
#include<iostream> using namespace std; #include<string> class Building; class GoodGay { public: GoodGay(); void visit();//Let the visit function access private members in Building void visit2();//Make the visit function not to access private members in Building Building* building; }; class Building { //Tell the compiler that the visit member function under the GoodGay class is a good friend of this class and can access private members. friend void GoodGay:: visit(); public: Building(); public: string m_SittingRoom;//living roomprivate: string m_BedRoom;//bedroom }; //Implement member functions outside the classBuilding::Building() { m_SittingRoom = "living room"; m_BedRoom = "bedroom"; } GoodGay::GoodGay() { building = new Building; } void GoodGay::visit() { cout << "The visit function is being accessed"<<building->m_SittingRoom << endl; cout << "The visit function is being accessed" << building->m_BedRoom << endl; } void GoodGay::visit2() { cout << "The visit2 function is being accessed" << building->m_SittingRoom << endl; //cout << "visit2 function is being accessed" << building->m_BedRoom << endl;} void test01() { GoodGay gg; (); gg.visit2(); } int main() { test01(); system("pause"); return 0; }
Summarize
That’s all for this article. I hope it can help you, and I hope you can pay more attention to more of my content!