C++-classes and objects (on)

First, the constructor

1. Concept

class Stack
{
    
    
public:
	void Init(int n = 4)
	{
    
    
		_a = (int*)malloc(sizeof(int) * n);
		if (!_a)
		{
    
    
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capcity = n;
	}
	void Destroy()
	{
    
    
		if (_a)
		{
    
    
			free(_a);
			_a = nullptr;
			_top = _capcity = 0;
		}
	}
private:
	int* _a;
	int _top;
	int _capcity;
};

int main()
{
    
    
	Stack st;
	st.Init();
	return 0;
}

Since functions are allowed to be defined in C++ classes, it is easy to get rid of the fact that we need to manually initialize objects as mentioned above. So C++ puts forwardConstructorthe concept.

Constructor: The constructor is a special member function with the same name as the class name, which is automatically called by the compiler when the class is instantiated to ensure that each data member has a suitable initial value and is used throughout the life of the object Called only once.
Notice: The constructor is not used to create the object, but to initialize the object. The constructor has no return value and supports function overloading.

Therefore, it is generally written like this in C++:

class Stack
{
    
    
public:
	Stack(int n = 4)
	{
    
    
		_a = (int*)malloc(sizeof(int) * n);
		if (!_a)
		{
    
    
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capcity = n;
	}
private:
	int* _a;
	int _top;
	int _capcity;
};
int main()
{
    
    
	Stack st1;
	Stack st2(8);
	return 0;
}

insert image description here

Do not use parameterless constructors like this:

Stack st3();

This would conflict with the declaration of a function named st3 with empty parameters and a return value of Stack.

2. Characteristics

  • The function name is the same as the class name
  • no return value
  • When a class is instantiated, the compiler automatically calls its constructor
  • Support function overloading
  • If there is no explicit definition of the constructor, the compiler will automatically generate a default constructor. Once the user explicitly defines the constructor, the compiler will not automatically generate
  • The default constructor automatically generated by the compiler, forBuilt-in types are not processed,rightThe custom type will call its default constructor
class Queue
{
    
    
public:

private:
	Stack st1;
	Stack st2;
	int _size;
};
int main()
{
    
    
	Queue q;
	return 0;
}

insert image description here

Even if the Queue class does not explicitly define a constructor, the compiler automatically generates a default constructor, which will call its default constructor for custom types, and does not process built-in types (It can be seen that the compiler also initializes _size, which is only for this compiler and is not universal)。

  • For the default constructor automatically generated by the compiler, the built-in type is not processed. In C++11, it is proposed to allow theNon-static member variables provide a default value, that is, a member variable is not initialized when the class is instantiated, then its value is the given default value.
class Queue
{
    
    
public:

private:
	Stack st1;
	Stack st2;
	int _size = 1;
};
int main()
{
    
    
	Queue q;
	return 0;
}

insert image description here

  • No-argument constructors, all default constructors, and those automatically generated by the compiler are all default constructors, and only one default constructor is allowed.

Second, the destructor

1. Concept

void Destroy()
{
    
    
	if (_a)
	{
    
    
		free(_a);
		_a = nullptr;
		_top = _capcity = 0;
	}
}

Contrary to the function of the constructor, when the object we defined involves dynamic memory development, we would manually call the Destroy function for resource management before. The destructor is inCalled automatically when the object is destroyed, complete the cleanup of resources in the object, andThe function name is ~ class name, there are no parameters, and function overloading is not supported.

class Stack
{
    
    
public:
	Stack(int n = 4)
	{
    
    
		_a = (int*)malloc(sizeof(int) * n);
		if (!_a)
		{
    
    
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capcity = n;
	}
	~Stack()
	{
    
    
		if (_a)
		{
    
    
			free(_a);
			_a = nullptr;
			_top = 0;
			_capcity = 0;
		}
	}
private:
	int* _a;
	int _top;
	int _capcity;
};

2. Characteristics

  • function name ~ class name
  • no parameters
  • Function overloading is not supported
  • Called automatically when the object is destroyed
  • When the user does not explicitly write a destructor, the compiler will automatically generate a destructor.
  • The destructor automatically generated by the compiler does not process the built-in type, and calls its destructor for the custom type.
class Stack
{
    
    
public:
	Stack(int n = 4)
	{
    
    
		_a = (int*)malloc(sizeof(int) * n);
		if (!_a)
		{
    
    
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capcity = n;
	}
	
private:
	int* _a;
	int _top;
	int _capcity;
};
void test1()
{
    
    
	Stack st1(6);
}
int main()
{
    
    
	test1();
	return 0;
}

The member variables in the Stack class are all built-in types, and the destructor automatically generated by the compiler does not process them, resulting in the space pointed to by _a not being released, resulting in memory leaks.

  • If the class does not involve the application of resources, the destructor can be directly used without writing the destructor automatically generated by the compiler, such as the Stack classWhen it comes to applying for resources, you must write a destructor

Three, copy construction

1. Concept

The copy constructor is an overloaded form of the constructor. It has only one parameter, which is a reference to the object of this class (generally decorated with const). When using an existing object to initialize and create a new object, the copy constructor will be called automatically.

2. Characteristics

  • The copy constructor is an overloaded form of the constructor
  • The parameter of the copy constructor is only one and must be a reference to the same object. If the method of passing by value is used, the compiler will report an error because infinite recursion will occur.
    If the method of calling copy construction is to use the method of passing value: because passing parameters by value will cause copy construction, that is to say, before we call copy construction, copy construction must occur once, repeated in turn, and infinitely recursive.
  • If no copy constructor is explicitly defined, the compiler will automatically generate a copy constructor. It simply copies the value of the built-in type, and calls its copy constructor for the custom type.
class Date
{
    
    
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
    
    
	Date d1(2023, 2, 10);
	Date d2(d1);
	return 0;
}

insert image description here

  • When the application of resources is involved in the class, the displayed copy constructor must also be written, otherwise a shallow copy is automatically generated.
class Stack
{
    
    
public:
	Stack(int n = 4)
	{
    
    
		_a = (int*)malloc(sizeof(int) * n);
		if (!_a)
		{
    
    
			perror("malloc fail");
			exit(-1);
		}
		_top = 0;
		_capcity = n;
	}
	~Stack()
	{
    
    
		if (_a)
		{
    
    
			free(_a);
			_a = nullptr;
			_top = 0;
			_capcity = 0;
		}
	}
private:
	int* _a;
	int _top;
	int _capcity;
};
int main()
{
    
    
	Stack st1;
	Stack st2(st1);
	return 0;
}

insert image description here

It can be seen that if the copy construction provided by the compiler is used, a shallow copy will occur, which will lead to a series of errors.

Stack(const Stack& st)
	{
    
    
		if (this != &st)
		{
    
    
			_a = (int*)malloc(sizeof(int) * st._capcity);
			if (!_a)
			{
    
    
				perror("malloc fail");
				exit(-1);
			}
			memcpy(_a, st._a, sizeof(int) * st._capcity);
			_top = st._top;
			_capcity = st._capcity;
		}
	}

Fourth, operator overloading

1. Concept

int main()
{
    
    
	vector<int> a(4, 0);
	for (int i = 0; i < 4; i++)
	{
    
    
		a[i] = i;
	}
	for (int i = 0; i < 4; i++)
	{
    
    
		cout << a[i] << " ";
	}
	return 0;
}

insert image description here

Vector is a data structure provided in the STL library, but you find that it can use [ ] to access its members like an array. In fact, this operator is overloaded [ ], which is essentially a function call.

operator overloading: In order to enhance the readability of the code, operator overloading is introduced in C++. Operator overloading is a function with a special function name, which also has a return value, function name, and parameter list, and is similar to a normal function. Its function name is operator (keyword) + operator to be overloaded

For example, we implement an array class ourselves to use this operator overload:

class Array
{
    
    
public:
	int& operator[](int i)
	{
    
    
		return a[i];
	}
private:
	int a[10];
	int size = 0;
};

int main()
{
    
    
	Array arr1;
	for (int i = 0; i < 5; i++)
	{
    
    
		arr1[i] = i;
	}
	for (int i = 0; i < 5; i++)
	{
    
    
		cout << arr1[i] << " ";
	}
	return 0;
}

insert image description here
Notice:

  • New operators cannot be created by concatenating other symbols: e.g. operator@
  • An overloaded operator must have a parameter of a custom type
  • Operators used for built-in types, whose meaning cannot be changed, for example: built-in integer +, whose meaning cannot be changed
  • When overloaded as a class member function, its formal parameters appear to be 1 less than the number of operands, because the first parameter of the member function is the hidden this
  • .* :: sizeof ?: . Note that the above 5 operators cannot be overloaded.

2. Assignment operator overloading

1. Operator overloading format

  • Parameter type: const T&, passing by reference can improve the efficiency of parameter passing, and also prevent errors due to the order of assignment.
  • Return value type: T&, return reference can improve the efficiency of return, and the purpose of return value is to support continuous assignment
  • Check if you assign a value to yourself
  • Return *this: to compound the meaning of continuous assignment

2. The assignment operator can only be overloaded as a class member function and cannot be overloaded as a global function
== Reason: If the == assignment operator is not explicitly implemented, the compiler will generate a default one. At this time, if the user implements a global assignment operator overload outside the class, it will conflict with the default assignment operator overload generated by the compiler in the class, so the assignment operator overload can only be a member function of the class.

3. When the user does not explicitly implement, the compiler will generate a default assignment operator overload,copy byte by value. Note: Built-in type member variables are directly assigned, while custom type member variables need to call the assignment operator overload of the corresponding class to complete the assignment.

class Date
{
    
    
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
	Date& operator[](const Date& d)
	{
    
    
		if (this != &d)
		{
    
    
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
	}
private:
	int _year;
	int _month;
	int _day;
};

Five, & overloading and const& overloading

These two default member functions generally do not need to be implemented by themselves, and the compiler will generate them by default.

class Date
{
    
    
public :
Date* operator&()
{
    
    
	return this ;

}
const Date* operator&()const
{
    
    
	return this ;
}
private :
	int _year ; // 年
	int _month ; // 月
	int _day ; // 日
};

Six, summary

1, class of 6default member function

  • Constructor
  • destructor
  • copy constructor
  • assignment operator overloading
  • & operator overloading
  • const& operator overloading

2. The common nature of default member functions is that the compiler will automatically provide default member functions when the user does not actively provide them.
3. The constructors and destructors automatically provided by the compiler do not process built-in types, but call their constructors and destructors for custom types.
4. The assignment operator overloaded copy construction automatically provided by the compiler will copy the value of the built-in type, and call its assignment operator overload and copy construction for the custom type.
5. C++ 11 provides default values ​​for built-in types.

Guess you like

Origin blog.csdn.net/Djsnxbjans/article/details/128973765