Immutable object
Immutable object: after an object is created, its content cannot be changed,
There is one exception: assign a value to this object in the form of an assignment operator (in the form of member copy),
That is, copy other objects to the current object. In this case, its content can be changed!
Immutable objects have many advantages:
1.1 thread safe: the value of the object cannot be changed, and there is no need to use special mechanisms to ensure synchronization, that is, it is safe for threads to share with each other!
1.2. Simplify program development, because it can be shared between online processes without using additional locking mechanism;
1.3. Improve the performance of the program, because it reduces the use of lock mechanism and other code to ensure memory consistency;
1.4. Those that can be reused can be cached and reused (instead of re creating one), just like string literals and integer numbers.
be careful:
Because immutable objects cannot be modified and reused, misuse will create a lot of garbage. String is a typical example.
Immutable class
Immutable class: the class to which the immutable object belongs;
To make class an immutable class, you need to meet the following three conditions at the same time:
(1) All data fields are set to "private" attribute;
(2) There is no setter changer function;
Changer functions: set functions and some functions that directly or indirectly change data members.
(3) There is also no getter accessor function that returns a reference or pointer that can change the data field object;
For example, there is a get function of a public attribute in class, which can return a pointer to the data member of a private attribute.
Externally, you can modify the data members of the private attributes in the class object through the pointer, that is, the object is variable!
Examples
Demonstrate that to create an immutable class, you need to meet the three conditions mentioned above.
It is suggested that variable names should be mixed case and start with lowercase letters. For example, setName is better understood!
"data.h" is as follows:
#pragma once / / compile the preprocessing instruction. The header file is included only once #include<iostream> #include<string> //Define a date class class date { private: //Private property int year=2021, month=5, day=16; public: //Public attribute // Here is the get function int getYear() { return year; } int getMonth() { return month; } int getDay() { return day; } // Here is the set function void setYear(int y) { year = y; } void setMonth(int m) { month = m; } void setDay(int d) { day = d; } // Here is the constructor // Default constructor; date() = default; // The constructor with parameters initializes the parameters using the initialization list of the constructor date(int y, int m, int d) :year{ y }, month{ m }, day{ d }{} //Convert the date into a string for better display std::string getString() { using namespace std; return to_string(year) + "--" + to_string(month) + "--" + to_string(day); } };
"employee.h" is as follows:
#pragma once / / compile the preprocessing instruction. The header file is included only once #include <iostream> #include<string> #include "data.h" // Enumeration type with scope limitation introduced by c++11 // Name of enumeration type: gender enum class gender { // The value range of enumeration type, i.e. enumeration constant; man, woman, // The compiler will automatically process the last enumeration constant even if a comma is added; }; class employee { private: //Private property std::string employee_name; // Employee name gender employee_gender; //Employee gender date employee_birthday; //Employee birthday public: // Public attribute // Here is the set function void setName(std::string name) {this->employee_name = name;} void setGender(gender Gender) {this->employee_gender = Gender;} void setBirthday(date Birthday) { this->employee_birthday = Birthday; } // Here is the get function std::string getName(){return employee_name; } gender getGender(){return employee_gender; } // The return type is a pointer to the date object; date* getBirthday(){ return &employee_birthday; } //Return private data member employee_ Pointer to birthday. //Convert to string form for better display // Converts the type of enumeration data to a string std::string getString() { using namespace std; //gender::man is an enumeration type with scope restrictions. How to use it string enum_gender = (employee_gender == gender::man ? "man" : "woman"); // employee_birthday is of date type, and the getString function is used to convert it into a string; string str_birthday = employee_birthday.getString(); return employee_name +"--"+ enum_gender + "--" + str_birthday; } // Here is the constructor, // The default constructor uses the form of delegate constructor, which saves code and makes the code logic clear; employee():employee("jn10010537", gender::man,date(2021,5,16)){} // The constructor with parameters initializes the parameters using the initialization list of the constructor employee(std::string name, gender Gender,date Birthday):employee_name{name},employee_gender{Gender}, employee_birthday{ Birthday }{} };
"cpp_main.cpp" is as follows:
#include<iostream> #include "data.h" #include "employee.h" // Demonstrate that to create an immutable class, three conditions must be met int main() { // Create an instantiated object of the employee class, and create the object using the parameterless default constructor employee obj_1; std::cout << "[1]" << obj_1.getString() << std::endl; // Modify the birthday and use the setter function obj_1.setBirthday(date(2014, 07, 07)); std::cout <<"[2]"<< obj_1.getString() << std::endl; // Modify the birthday and use the getter function obj_1.getBirthday()->setYear(2030); std::cout << "[3]" << obj_1.getString() << std::endl; // The run window remains resident std::cin.get(); return 0; }
Run cpp_main.cpp source files are as follows: