[c++] Encapsulation, Initialization and Cleaning of Objects

Keywords: C++ OOP

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:

  1. Public public permissions

  2. protected Protect Permissions

  3. 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 (){}

  1. Constructor, no return value, no void
  2. The function name is the same as the class name
  3. Constructors can have parameters, so overloads can occur
  4. Programs automatically invoke constructs when they invoke objects, do not need to invoke them manually, and only invoke them once

Destructor syntax: ~Class name (){}

  1. Destructor, no return value, no void
  2. The function name is the same as the class name, preceded by a symbol~
  3. Destructors cannot have parameters and therefore cannot be overloaded
  4. 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:

  1. bracketing
  2. Display method
  3. 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

  1. Initialize a new object with a created object
  2. How values are passed to function parameters
  3. 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

  1. Default constructor (no arguments, empty body)
  2. Default destructor (no parameters, empty body)
  3. Default copy function, heap properties are "value" copied

The constructor call rules are as follows

  1. If a user-defined parametric constructor exists, c++ will no longer provide a default constructor, but will provide a default copy function

  2. 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:

  1. Static member variable

    (1).All objects share the same data

    (2) Allocation of memory during compilation

    (3). Intra-class declarations, out-of-class initialization

  2. 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;
}

Posted by lalabored on Fri, 08 Oct 2021 10:42:15 -0700