Write at the beginning
Reference Black Horse Programmer c++ Core Programming
4. Classes and Objects
4.1 Packaging
Encapsulation is one of the three object-oriented features of C++.
Significance of 4.1.1 Packaging
(1). Express the things in life by taking attributes and behaviors as a whole
(2) Control of attributes and behaviors with privileges
Significance of packaging:
When designing classes, attributes and behaviors are written together to represent things
Example 1: Design a circle class to find the perimeter of a circle
#include <bits/stdc++.h> using namespace std; const double PI = 3.14; //The meaning of packaging: //Use attributes and behaviors as a whole to represent things in life class Circle { public://Public Access //attribute int m_r;//radius //behavior //Get the perimeter of a circle double calculateZC() { //2*pi*r //Get the perimeter of a circle return 2 * PI * m_r; } }; int main() { //Create objects of a circle by using the circle class //c1 is a specific circle Circle c1; c1.m_r = 10;//Assigning the radius of a circle object cout << "The circumference of a circle is: " << c1.calculateZC() << endl; return 0; }
Example 2:
#include <bits/stdc++.h> using namespace std; //Student Class class Student { public: string m_name; int m_id; public: void setName(string name) { m_name = name; } void setID(int id) { m_id = id; } void showStudent() { cout << "name:" << m_name << endl << "ID:" << m_id << endl; } }; int main() { Student stu; stu.setName("leimingze"); stu.setID(016511); stu.showStudent(); return 0; }
Encapsulation meaning two:
Classes can be designed to control properties and behaviors with different permissions
There are three types of access rights:
-
Public public permissions
-
protected Protect Permissions
-
private Private Rights
Example
#include <bits/stdc++.h> using namespace std; //Three permissions //public privileges //Protect permission protected //private Rights private class Person { public: string m_Name;//Name, Public Rights protected: string m_Car;//Automobile, Protection Rights private: int m_Password;//Bank Card Password, Private Rights public: void func() { m_Name = "leimingze"; m_Car = "Tractor"; m_Password = 123456; } }; int main() { Person p; p.m_Name = "Li Si"; //p.m_Car="Bence";Protection rights out of class access is not available //p.m_Password=123;//Private rights not accessible outside class //p.func(); cout << p.m_Name; return 0; }
4.1.2 Strct and class differences
The difference between struct and class in C++ is that the default access permissions are different
Difference:
(1) The default permission for struct is public
(2) class default permission is private
#include <bits/stdc++.h> using namespace std; class C1 { int m_A;//Private rights by default }; struct C2 { int m_A;//Default to Public Privileges }; int main() { C1 c1; c1.m_A = 10;//Error, Access Private C2 c2; c2.m_A = 10;//Correct, access rights public return 0; }
4.1.3 Member property set to private
**Advantage 1:**Set all member properties to private, allowing you to control read and write permissions yourself
**Advantage 2:**Team-mate write rights, we can check the validity of the data
Example:
#include <bits/stdc++.h> using namespace std; class Person { private: string m_Name;//Name, readable and writable int m_Age;//Age, read-only string m_Lover;//Valentine, write only public: void setName(string name)//Name Settings Readable and Writable { m_Name = name; } string getName() { return m_Name; } int getAge()//Getting Age { return m_Age; } void setAge(int age)//Set Age { if (age < 0 || age>150) { cout << "You old goblin" << endl; return; } m_Age = age; } void setLover(string lover)//Valentine set to write-only { m_Lover = lover; } }; int main() { Person p; p.setName("leimingze");//Name Settings cout << "Full name:" << p.getName() << endl; p.setAge(50);//Age Settings cout << "Age:" << p.getAge() << endl; p.setLover("Hey");//Valentine Settings //Cout << "Valentine:" << p.m_Lover << endl;//Write-only is not readable return 0; }
4.2 Initialization and Cleaning of Objects
(1) The electronic products we buy in our life will basically have factory settings, and some of our own information data will be deleted to ensure safety when we are not in use one day.
(2) Object-oriented in C++ comes from life, and each object also has its initial settings and settings for cleaning up data before the object is destroyed.
4.2.1 Constructors and Destructors
Initialization and cleanup of objects are two very important security issues
If it is not initialized, the consequences of its use are unknown
Using the same object or variable without cleaning it up in time can cause certain security problems.
c++ solves these problems using constructors and destructors, which are automatically called by the compiler to initialize and clean up objects
Initialization and cleanup of objects are things the compiler forces us to do, so we don't provide constructs and destructions, the compiler provides them
The constructor and destructor provided by the compiler are empty implementations
(1) Constructor: The main function is to assign values to the object member properties when the object is created. The constructor is called automatically by the compiler and does not need to be called manually.
(2) Destructors: The main function is to make system calls automatically and perform some cleanup before the object is destroyed
**Constructor syntax: **Class name (){}
- Constructor, no return value, no void
- The function name is the same as the class name
- Constructors can have parameters, so overloads can occur
- Programs automatically invoke constructs when they invoke objects, do not need to invoke them manually, and only invoke them 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 and therefore cannot be overloaded
- The program calls the destructor automatically before the object is destroyed, no need to call it manually, and only once
#include <bits/stdc++.h> using namespace std; class Person { public: Person()//Constructor { cout << "Person Constructor call" << endl; } ~Person() { cout << "Person Destructor call for" << endl; } }; /* void test01() { Person p; } */ int main() { //test01(); Person p; //Person's constructor call appears here cout << "aaaaaa" << endl; system("pause"); return 0; //Person's destructor call appears here }
Classification and Call of 4.2.2 Constructor
Two types of classification:
By parameters, they are divided into parametric and parametric constructs
Classified by type: ordinary and copy constructs
Three ways of calling:
- bracketing
- Display method
- Implicit Conversion
Example
#include <bits/stdc++.h> using namespace std; //Constructor Classification //Classify by parameter into parameterized and nonparameterized constructions, also known as default constructors //Classify into common and copy constructs by type class Person { public: Person()//No parameter (default) constructor { cout << "non-parameter constructor" << endl; } Person(int a)//Parametric constructor { age = a; cout << "Parametric constructor" << endl; } Person(const Person& p)//copy constructor { age = p.age; cout << "copy constructor" << endl; } ~Person()//Destructor { cout << "Destructor" << endl; } public: int age; }; //Calls to constructors //Call parameterless constructor void test01() { Person p; } void test02() { //Parentheses, common Person p1(10); //Note: Calls to parameterless constructors cannot be parenthesized, and compilers will consider this a function declaration //Person p2(); cout << "---------------" << endl; //Explicit method Person p2 = Person(10); cout << "-----------------" << endl; Person p3 = Person(p2); //Person(10) is an anonymous object written alone and destructed immediately after the current line ends cout << "------------------" << endl; //Implicit Conversion Person p4 = 10;//Person p4 = Person(10); cout << "--------------------" << endl; Person p5 = p4;//Person p5 = Person(p4); //Note: You cannot initialize anonymous object compilers as object declarations using copy constructors //Person(p3)===Person p3; } int main() { //test01(); test02(); system("pause"); return 0; }
Time to invoke 4.2.3 copy constructor
There are usually three situations when a copy constructor is called in cpp
- Initialize a new object with a created object
- How values are passed to function parameters
- Return local objects as values
Example
#include <bits/stdc++.h> using namespace std; class Person { public: int mAge; public: Person() { cout << "non-parameter constructor" << endl; mAge = 0; } Person(int age) { cout << "Parametric constructor" << endl; mAge = age; } Person(const Person& p) { cout << "copy constructor" << endl; mAge = p.mAge; } ~Person() { cout << "Destructor" << endl; } }; //Initialize a new object with a created object void test01() { Person man(100);//p object has been created Person newman(man);//Call copy constructor Person newman2 = man;//copy construction //Person newman3; //newman3 = man; //Not calling copy constructor, assignment operation } void dowork(Person p1) {}//How values are passed to function parameters void test02() { Person p;//non-parameter constructor dowork(p);//Equivalent to Person p1=p; } Person dowork2()//Returns a local object by value, and returns by copying an object { 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 Call Rules
By default, the c++ compiler adds at least three functions to a class
- Default constructor (no arguments, empty body)
- Default destructor (no parameters, empty body)
- Default copy function, heap properties are "value" copied
The constructor call rules are as follows
-
If a user-defined parametric constructor exists, c++ will no longer provide a default constructor, but will provide a default copy function
-
If a user-defined copy constructor is present, c++ will not provide other constructors
Example
#include <bits/stdc++.h> using namespace std; class Person { public: int age; public: //No parameter (default) constructor Person() { cout << "non-parameter constructor" << endl; } //Parametric constructor Person(int a) { age = a; cout << "Parametric constructor" << endl; } Person(const Person& p) { age = p.age; cout << "copy constructor" << endl; } ~Person() { cout << "Destructor" << endl; } }; void test01() { Person p1(18); //If you do not write a copy construct, the compiler automatically adds a copy construct and does a shallow copy operation Person p2(p1); cout << "p2 Age:" << p2.age << endl; } void test02() { //If the user provides a reference construct, the compiler will not default the construct and will provide a copy construct Person p1;//If the user does not provide the default construct himself, an error will occur Person p2(10);//User provides construct reference Person p3(p2);//If the user does not provide the reference, the compiler provides it //If the user provides a copy construct, the compiler does not provide other constructors Person p4;//If the user does not provide the default construct himself, an error will occur Person p5(10);//If the user does not provide the construct himself, an error will occur Person p6(p5);//Users provide copy constructs themselves } int main() { test01(); system("pause"); return 0; }
4.2.5 Deep and Shallow Copies
Shallow copy is a classic interview question and a pit
**Shallow copy:**Simple assignment copy operation
**Deep copy:**Re-apply space in heap area for copy operation
Example
#include <bits/stdc++.h> using namespace std; class Person { public: int m_age; int* m_height; public: Person()//non-parameter constructor { cout << "non-parameter constructor" << endl; } Person(int age, int height)//Parametric constructor { cout << "Parametric constructor" << endl; m_age = age; m_height = new int(height); } //copy constructor Person(const Person& p) { cout << "copy constructor" << endl; //The system's own copy constructor has a duplicate release heap area problem //If you do not create new memory in the heap using a divine copy, it will result in duplicate release from a shallow copy m_age = p.m_age; m_height = new int(*p.m_height); } ~Person() { cout << "Destructor" << endl; if (m_height != NULL) { delete m_height;//Delete data stored in the heap } } }; void test01() { Person p1(18, 100); Person p2(p1); cout << "p1 Age:" << p1.m_age << "height: " << *p1.m_height << endl; cout << "p2 Age:" << p2.m_age << "Height:" << *p2.m_height << endl; } int main() { test01(); system("pause"); return 0; }
Summary: If a property is open in a stack area, be sure to provide a copy constructor yourself to prevent problems caused by stack copies.
4.2.6 Initialization List
Effect:
c++ provides initialization list syntax to initialize properties
Syntax: Constructor (): Attribute 1 (value 1), Attribute 2 (value 2)...{}
Example
#include <bits/stdc++.h> using namespace std; class Person { private: int m_A; int m_B; int m_C; public: //Traditional Initialization //Person(int a, int b, int c) //{ // m_A = a; // m_B = b; // m_C = c; //} Person(int a, int b, int c) :m_A(a), m_B(b), m_C(c) {} void PrintPerson() { cout << "mA:" << m_A << endl; cout << "mB:" << m_B << endl; cout << "mC:" << m_C << endl; } }; int main() { Person p(1, 2, 3); p.PrintPerson(); return 0; }
4.2.7 Class Objects as Class Members
A member of a c++ class can be an object of another class, which we call an object member
eg.
class A{} class B { A a; }
Class B has object A as a member and object A as a member
So when B objects are created, in which order do A and B construct and destruct first?
Example
#include <bits/stdc++.h> using namespace std; class Phone { public: string m_PhoneName; public: Phone(string name) { m_PhoneName = name; cout << "Phone structure" << endl; } ~Phone() { cout << "phone Destruction" << endl; } }; class Person { public: string m_Name; Phone m_Phone;//member object public: Person(string name, string pName) :m_Name(name), m_Phone(pName)//Initialization { cout << "Person structure" << endl; } ~Person() { cout << "Person Destruction" << endl; } void playGame() { cout << m_Name << "Use" << m_Phone.m_PhoneName << endl; } }; void test01() { //When a member of a class is an object of another class, we call that member an object member //Order of construction: invoke the construction of object members before invoking this class construction //Analogue stack in which the destructive order is opposite to the construction order (descendants form the parent, letters are released, and fonts are free) Person p("leimingze", "Apple x"); p.playGame(); } int main() { test01(); return 0; }
4.2.8 Static members
A static member is a member variable and a member function preceded by the keyword static, called a static member
Static members are divided into:
-
Static member variable
(1).All objects share the same data
(2) Allocation of memory during compilation
(3). Intra-class declarations, out-of-class initialization
-
Static member function
(1). All objects share the same function
(2). Static member functions can only access static member variables
Static member variable
#include <bits/stdc++.h> using namespace std; class Person { public: static int m_A;//Static member variable //Static member variable characteristics; //1 Allocate memory during compilation //Intra-class declaration, out-of-class initialization //All three objects share the same data private: static int m_B;//Initialization of static member variables is also accessible }; int Person::m_A = 10; int Person::m_B = 10; void test01() { //Two ways to access static member variables //1 By object Person p1; p1.m_A = 100; cout << "p1.m_A:" << p1.m_A << endl; Person p2; p2.m_A = 200; cout << "p1.m_A = " << p1.m_A << endl;//Sharing the same data is, so m_A changes cout << "P2.m_A = " << p2.m_A << endl; //2 By class name cout << "m_A = " << Person::m_A << endl; //Cout<<"m_B ="< Person::m_B< endl;//Private rights are inaccessible } int main() { test01(); return 0; }
Static member function
#include <bits/stdc++.h> using namespace std; class Person { public: static int m_A;//Static member variable int m_B;//This must be called through an object, and static is globally shared and cannot access non-static quantities public: //Static Member Function Features //1 Program shares a function //2 Static member functions can only access static member variables static void func() { cout << "func call" << endl; m_A = 100; //m_b=100; //Error, non-static program variables are not accessible } private: static void func2()//Static member functions also have access { cout << "func2 call" << endl; } }; int Person::m_A = 10; void test01() { //Two ways to access static member variables //1 Access through objects Person p1; p1.func(); //2 By class name, all are common, not belonging to a single Person::func(); //Person::func2(); //Private static permissions are inaccessible } int main() { test01(); return 0; }