SoFunction
Updated on 2025-03-10

Do you really understand the object characteristics and friendliness of C++?

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&lt;iostream&gt;
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 &lt;&lt; "Person's default constructor call" &lt;&lt; endl;
	}
	Person(int age) {
		cout &lt;&lt; "Person's parameter constructor call" &lt;&lt; endl;
		m_Age = age;
	}
	Person(const Person &amp;p) {
		cout &lt;&lt; "Person's copy constructor call" &lt;&lt; endl;
		m_Age = p.m_Age;
	}
	~Person() {
 		cout &lt;&lt; "Person destructor call" &lt;&lt; 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 &lt;&lt; "The age of p2 is:" &lt;&lt; p2.m_Age &lt;&lt; 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&lt;iostream&gt;
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&amp; p) {
		cout &lt;&lt; "Person's copy constructor call" &lt;&lt; endl;
		m_Age = p.m_Age;
}
 	~Person() {
		cout &lt;&lt; "Person's destructor call" &lt;&lt; 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 &lt;&lt; "The age of p2 is:" &lt;&lt; p2.m_Age &lt;&lt; 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&lt;iostream&gt;
using namespace std;
//Deep copy and shallow copyclass Person {
public:
	Person() {
		cout &lt;&lt; "Person's default constructor call" &lt;&lt; endl;
	}
	Person(int age,int height) {
		m_Age = age;
		m_Height = new int(height);
		cout &lt;&lt; "Person's parameter constructor call" &lt;&lt; endl;
	}
	Person(const Person &amp;p) {
		cout &lt;&lt; "Person copy constructor call" &lt;&lt; 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 &lt;&lt; "Person's destructor call" &lt;&lt; endl;
	}
	int m_Age;//age	int* m_Height;//height};
void test01() {
	Person p1(18,160);
	cout &lt;&lt; "The age of p1 is:" &lt;&lt; p1.m_Age &lt;&lt;"Height is:"&lt;&lt;*p1.m_Height &lt;&lt; endl;
	Person p2(p1);
	cout &lt;&lt; "The age of p2 is:" &lt;&lt; p2.m_Age &lt;&lt;"Height is:"&lt;&lt;*p2.m_Height &lt;&lt; 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&lt;iostream&gt;
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 &lt;&lt; "m_A = " &lt;&lt; p.m_A &lt;&lt; endl;
	cout &lt;&lt; "m_B = " &lt;&lt; p.m_B &lt;&lt; endl;
	cout &lt;&lt; "m_C = " &lt;&lt; p.m_C &lt;&lt; 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&lt;iostream&gt;
using namespace std;
//Class object as class member//Mobile phoneclass Phone {
public:
	Phone(string pName) {
		cout &lt;&lt; "Phone's constructor call" &lt;&lt; endl;
		m_PName = pName;
	}
	~Phone() {
		cout &lt;&lt; "Phone's destructor call" &lt;&lt; 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 &lt;&lt; "Person's constructor call" &lt;&lt; endl;
	}
	~Person() {
		cout &lt;&lt; "Person's destructor call" &lt;&lt; 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 &lt;&lt; p.m_Name &lt;&lt; "Hold" &lt;&lt; p.m_Phone.m_PName &lt;&lt; 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&lt;iostream&gt;
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 &lt;&lt; "Call of static void func" &lt;&lt; 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 &lt;&lt; "Call of static void func2" &lt;&lt; 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&lt;iostream&gt;
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 &lt;&lt; "size of p = "&lt;&lt;sizeof(p) &lt;&lt; endl;
}
void test02() {
	Person p;
	cout &lt;&lt; "size of p = " &lt;&lt; sizeof(p) &lt;&lt; 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&lt;iostream&gt;
using namespace std;
class Person {
public:
	Person(int age) {
		//This pointer points to the object to which the called member function belongs		this-&gt;age = age;
	}
	int age;
	Person PersonAddAge(Person &amp;p) {
		this-&gt;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 &lt;&lt; "The age of p1 is:" &lt;&lt;  &lt;&lt; endl;
}
//2. Return the object itself with *thisvoid test02() {
	Person p1(10);
	Person p2(10);
	//Chain programming idea	(p1).PersonAddAge(p1).PersonAddAge(p1);
	cout &lt;&lt; "The age of p2 is:" &lt;&lt;  &lt;&lt; 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&lt;iostream&gt;
using namespace std;
//Null pointer calls member functionclass Person {
public:
 	void showClassName() {
		cout &lt;&lt; "this is Person class" &lt;&lt; endl;
	}
	void showPersonAge() {
		//The reason for the error is that the incoming pointer is NULL		if (this == NULL)
		{
			return;
		}
		cout &lt;&lt; "age = " &lt;&lt;this-&gt; m_Age &lt;&lt; endl;
	}
	int m_Age;
};
void test01() {
	Person* p = NULL;
	//p-&gt;showClassName();
	p-&gt;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&lt;iostream&gt;
using namespace std;
//Null pointer calls member functionclass Person {
public:
 	void showClassName() {
		cout &lt;&lt; "this is Person class" &lt;&lt; endl;
	}
	void showPersonAge() {
		//The reason for the error is that the incoming pointer is NULL		if (this == NULL)
		{
			return;
		}
		cout &lt;&lt; "age = " &lt;&lt;this-&gt; m_Age &lt;&lt; endl;
	}
	int m_Age;
};
void test01() {
	Person* p = NULL;
	//p-&gt;showClassName();
	p-&gt;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&lt;iostream&gt;
using namespace std;
#include&lt;string&gt;
//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 &lt;&lt; "Good gay friend global function is being accessed:" &lt;&lt; building-&gt;m_SittingRoom &lt;&lt; endl;
	cout &lt;&lt; "Good gay friend global function is being accessed:"&lt;&lt;building-&gt;m_BedRoom &lt;&lt; endl;
}
void test01() {
	Building building;
	goodGay(&amp;building);
}
int main() {
	test01();
	system("pause");
	return 0;
}

Become a friend

#include&lt;iostream&gt;
using namespace std;
#include&lt;string&gt;
//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 &lt;&lt; "Good friends are visiting:"&lt;&lt;building-&gt;m_SittiingRoom &lt;&lt; endl;
	cout &lt;&lt; "Good friends are visiting:" &lt;&lt; building-&gt;m_BedRoom &lt;&lt; endl;
}
void test01() {
	GoodGay gg;
	();
}
int main() {
	test01();
	system("pause");
	return 0;
}

Member functions are friends

#include&lt;iostream&gt;
using namespace std;
#include&lt;string&gt;
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 &lt;&lt; "The visit function is being accessed"&lt;&lt;building-&gt;m_SittingRoom &lt;&lt; endl;
	cout &lt;&lt; "The visit function is being accessed" &lt;&lt; building-&gt;m_BedRoom &lt;&lt; endl;
}
void GoodGay::visit2() {
	cout &lt;&lt; "The visit2 function is being accessed" &lt;&lt; building-&gt;m_SittingRoom &lt;&lt; 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!