Multiple acting classes and objects

catalogue

1, Understanding of class

2, Access qualifier and encapsulation of class

3, Scope and instantiation of class

4, Calculation of object size of class

5, this pointer of class member function

6, Constructor

7, Destructor

8, Copy constructor

9, Operator overloading

10, Implementation of date class

Get the number of days per month

Create constructor

Compare date size

Date + - Days

Front + +, --, rear + +--

Date - date

Ask how many days a day is a day of the week

Overload input / output operators

11, const member

12, explicit keyword

13, static member

14, A new method of member initialization in C++11

15, Friends

16, Inner class

1, Understanding of class

Process oriented:

C language is process oriented, focusing on the process, analyzing the steps to solve the problem, and gradually solving the problem through function call

object-oriented:

C + + is based on object-oriented and focuses on objects. It divides a thing into different objects and completes it by the interaction between objects

For example, design a simple takeout system

Process oriented: focus on the process of placing orders, receiving orders, delivering meals, etc. Code to function level

Object oriented: focus on the implementation of class objects and the relationship between class objects, users, businesses, riders and the relationship between them. Reflected in the code level -- the design of classes and the relationship between classes

Class introduction

In C, the struct can only define variables, while in C + +, the struct can define variables and functions

This is because C + + is compatible with C, so the structure defined by struct can also define functions

Class definition

In C + +, a new concept of this structure is introduced, which is called class, and the keyword is class

class name

{class body};

Note: like the structure, don't forget the semicolon (;) at the end

Class body can store member variables and member functions

Note: if a function is defined in a class, the compiler may treat it as an inline function. Generally, it puts the declaration of the member function and defines the member function outside the class

2, Access qualifier and encapsulation of class

Access qualifiers: public, private, protected

Members decorated with public can be accessed directly outside the class

Protected and private modified members cannot be accessed directly outside the class (protected and private are similar here)

The scope of access rights starts from where the access qualifier appears until the next access qualifier appears

If there is no access qualifier, the scope ends with the} class

The default access permission of class is private and struct is public (because struct is compatible with C)

encapsulation

Concept: organically combine data and methods of operating data, hide the attributes and implementation details of the object, and only expose the interface to interact with the object

Because of encapsulation, member variables are generally placed in private and member functions in public

3, Scope and instantiation of class

Scope of class

Class defines a new scope and defines members outside the class. You need to use the:: scope resolver to indicate which class domain the members belong to

Class instantiation

Concept: the process of creating objects with class types is called class instantiation

Class is just a model that defines which members there are, but does not allocate actual space to store it

Class is similar to the structure in C language, except that one is to create structure variables and the other is to create objects. The instantiated objects occupy the actual physical space and store class member variables. As shown in the figure below, d1 is an object and the following is to access member functions

Class instantiates an object, just like building a house with architectural design drawings in reality, and class is like design drawings

4, Calculation of object size of class

For classes, only member variables are saved, and member functions are stored in public code segments. Therefore, when calculating the size of a class or object, only member variables are used

Conclusion: to calculate the size of a class or class object, only look at the member variables and consider the memory alignment. The C + + memory alignment rules are consistent with the C structure

 

The space occupied by an empty class is the same as that of a class with only member functions, and 1 byte will be given. This 1 byte does not store valid data, but only for space occupation, indicating that the object exists

5, this pointer of class member function

As can be seen from the above figure, d1 and d2 are the same Print function called

There is no distinction between different objects in the function body. When d1 calls the Print function, how does the function know that d1 object should be set instead of d2 object?  

The C + + compiler adds a hidden pointer parameter to each "non static member function" so that the pointer points to the current object. The operation of all member variables in the function body is accessed through the pointer, which is the hidden this pointer

 

In fact, the calling member function should be as shown in the figure above, but this is hidden

Characteristics of this pointer

Type of this pointer: class type * const

It can only be used inside the "member function", but generally, it will not be displayed as follows

This pointer is essentially a formal parameter of a member function. When an object calls a member function, the object address is passed to this parameter as an argument. The declared formal parameter this cannot be displayed

This pointer is the first implicit pointer parameter of a member function. It cannot be displayed or passed to this

Note: this pointer is usually stored on the stack. Some compilers will put it in registers, such as vs2013 and ecx

normal operation

Run crash

 

analysis:

Although P is a null pointer, it will not compile and report an error when p calls the member function, because the null pointer is not a syntax error and the compiler cannot check it

Although P is a null pointer, there will be no null pointer access when p calls the member function, because the member function does not exist in the object

Here, p is passed as an argument to the hidden this pointer

6, Constructor

Concept: the constructor is a special member function with the same name as the class name. It is automatically called by the compiler when creating a class type object. It is called only once in the life cycle of the object. Its main function is to initialize the object, not to create an object in an open space

characteristic

The function name is the same as the class name

No return value

When an object is instantiated, the compiler automatically calls the corresponding constructor

Constructors can be overloaded

Date d1; // Call the parameterless constructor, which cannot be followed by parentheses, otherwise it is the function declaration

Date d2 (2015, 1, 1); // Call the constructor with parameters

If the constructor is not explicitly defined in the class, the C + + compiler will automatically generate a parameterless default constructor. Once the user explicitly defines the constructor, the compiler will no longer generate it

Member variables of built-in types (basic types: char, int, double, etc.) are not initialized

For a member variable of a custom type, it will call its default constructor for initialization. If there is no default constructor, an error will be reported

 

Default constructor: full default, no parameters. We don't write the constructor generated by the compiler by default

Both parameterless constructors and fully default constructors are called default constructors, and there can only be one default constructor

Although the parameterless constructor and the full default constructor are function overloads from the syntax, there is ambiguity in the call

For the convenience of distinguishing, as shown in the figure above, for example, the formal parameter is year and the member variable is_ Year, add one at the beginning_

Note: global objects are constructed before local objects

On constructor

The previous constructors are initialized in the function body. The statements in the constructor body can only be called initial value, not initialization. Because initialization can only be initialized once, and the constructor body can be assigned multiple times

Initializing list initializing member variables

Initialization list - where member variables are defined

Class name (parameter) colon (:) member variable (formal parameter or constant) comma (,) member variable (formal parameter or constant)

be careful:

Each member variable can only appear once in the initialization list (initialization can only be initialized once)

Class contains the following members, which must be placed in the initialization list for initialization

Reference member variable

const member variable

  

Custom type member (this class has no default constructor)

Reason: the above three variables must be initialized at the time of definition, otherwise an error will be reported during compilation. Member variables of other types can be initialized anywhere, such as int year, int month, etc

Try to use the initialization list for initialization, because no matter whether you use the initialization list or not, for custom type member variables, you will use the initialization list first

The declaration order of a member variable in a class is its initialization order in the initialization list, regardless of its order in the initialization list, as shown in the following figure

7, Destructor

Concept: when the object is destroyed, it will automatically call the destructor to clean up some resources of the class

characteristic

The destructor name is preceded by a character in the class name~

No parameter, no return value

A class has only one destructor. If not explicitly defined, the system will automatically generate the default destructor

At the end of the object life cycle, the C + + compilation system automatically calls the destructor

Similar to the default constructor generated by the compiler, the built-in type member variable is not processed, and the destructor of the custom type member variable is called back

For the space requested on the heap, you have to add free to the destructor and set the pointer to nullptr, as shown in the following figure

 

The constructor that first calls will be destructed after the meeting, and the constructor after that will be destructed.

Local objects are destructed first and global objects are destructed later. If a static object is local, it destructs first and then local objects

8, Copy constructor (special member function)

Concept: there is only a single formal parameter, which is a reference to the object of this class type (commonly used const decoration). It is automatically called by the compiler when creating a new object with an existing class type object

features

Copy constructor is an overloaded form of constructor

There is only one parameter of the copy constructor, and the parameter must be passed by reference. Using the value passing method will cause infinite recursive calls

Because to call the copy structure, you need to pass the parameters first, and the value and parameter transfer is a copy structure. To call the copy structure, you need to pass the parameters first, and the value and parameter transfer is a copy structure, which will be called infinitely recursively

If the definition is not displayed, the system generates the default copy constructor

Built in type members, which will complete the copy in byte order (shallow copy)

A custom type member will call its copy construct

9, Operator overloading

In order to enhance the readability of the code, C + + introduces operator overloading, which is a function with a special function name

Return type + operator + operator to be overloaded (>, <, +) + parameter list

be careful

You cannot create a new operator by concatenating other symbols: for example, operator @

Overloaded operators must have an operand of class type or enumeration type

The meaning of operators used for built-in types cannot be changed. For example, the meaning of built-in integer +

When an overloaded function is a class member, its formal parameters appear to be 1 less than the number of operands. The operator of the member function has a default formal parameter this, which is limited to the first formal parameter

Defined in class

The definition is global. Pay attention to ensure that the members of the class are accessible, otherwise an error will be reported in the compilation (private members are not accessible)

Because the member function of the class will have a hidden this pointer, there will be one less parameter than the global

.* ,:: ,sizeof ,?: ,. Note that the above five operators cannot be overloaded (note that. *, not *)

The difference between copy construction and assignment overload

Copy construction: copy and initialize an existing object, and create an instantiated object immediately

Assignment overload: copy assignment between two existing objects

For assignment overload, it is better to use reference return, and copy structure will appear in value passing copy

 

The compiler generates assignment overloads by default, which is similar to what copy constructs do

Built in type members will complete byte order value copy - shallow copy

A custom type member variable will call its operator=

10, Implementation of date class

Get the number of days per month

First, create a static array, and then take the number of days of each month as the size of each element. It is best to create an array of 13 elements. In this way, the first element is assigned a 0, and the other elements are assigned according to the talent value of each month, that is, arr[1]=31,arr[2]=28

Because the number of days in February changes, we have to consider ordinary years and leap years. The number of days in leap years is + 1

Create constructor

Here, the default value method is used to initialize the member variable

Note: only one of the declarations and definitions can have a default value. If it exists at the same time, an error will be reported

At the same time, we have to judge whether the date is legal. If not, explain it and print the date

Compare date size

There are 6 operators in total, namely >, <, > =, < =,! =, = =, Just write > and = =, and the rest can be reused

Overloading the > operator

First, judge the size of the year. d1 is true

If the years are equal, judge the months

If the year and month are equal, judge the day

In addition to the above three cases, it is d2 large

Overloading = = operator

When the month, year and day are equal, they are equal, so use & & connection

For example, overloading the > = operator can be written as d1 > d2 or d1 = = d2

   

Date + - Days

Date + = days

First + = days

Then judge_ Is day greater than the number of days in that month

If it is greater than the number of days in that month, subtract the number of days in that month, month + 1

If month + 1 is followed by 13, that year will be + 1 and month will be assigned as 1

Finally, * this is returned, and the copy structure can be reduced by passing reference

Date - = days

First - = days

Then judge_ Is day < = 0

Enter the cycle, first month-1, then judge whether the month is 0, 0, year-1, and the month is assigned as 12_ day + days of that month

It's better to return * this and use reference return to reduce parameters

Date + days

First, you have to create a temporary date variable, because you can't change the original object and use the copy structure

Then reuse the previous + = days for ret

Date - Days

Same as date + days

Note: date + - days cannot be returned by reference because it is a temporary variable

Front + +, --, rear + +--

Front++

Pass reference return to reduce copy structure

Postposition++

You have to create a temporary variable because post + + is used first and then++

Post + + has more int type parameters than pre + +, which is to distinguish between pre + + and post + +, and can only be int, which is specified by C + +

Pre -- and post -- the same

Date - date

First create a temporary variable for two dates. The initial default * this is larger and d2 is smaller

So create another variable of type int and assign a value of 1. The default value is * this > D2

 

Then compare * this and d2. If they are different from the initial default, they will be reversed and the flag will be - 1

Then use the while loop to judge if max is not equal to min, and jump out of the loop if it is equal. The number of days in the loop is + 1 and min+1

It is best to return the product of days and flag, which means that the subtraction is positive or negative

 

Ask how many days a day is a day of the week

You need to find a reference date. Here is January 1, 1900, which happens to be Monday, which is convenient for processing

Then create a pointer array with 7 elements, representing Monday to Sunday

Reuse the previous date date, and then use its return value% 7

Overload input / output operators

Overload output operator

Note: the function that overloads the output operator cannot become a member function of the class, because the first parameter of the member function is the this pointer, that is, the first operand of <. If it is a member function, it must be written as D1 < < cout, which obviously does not meet our expectations, so we have to define this function as a global function

The void return type is not used here because if it is continuously output, the void return cannot achieve the purpose, such as cout < < D1 < < D2

The same is true for input operator overloading, except that const cannot be added to the object

11, const member

As shown in the figure above, the object modified by const cannot call the member function Print(), because the implicit this pointer is involved, and the formal parameter is

A* const this: the argument is modified by const to enlarge the permission, so the compilation reports an error. Because this is hidden, const cannot be added to the parameter, so there is const modified member function

For the address (&), there is no need to overload, because the compiler will generate the overload of the default address. Overload is only required in special cases, such as to let others get the specified content

Summary: it is good to add const to member functions. It is recommended to add const if possible, so that ordinary objects and const objects can be called. However, if you want to modify the member function of member variables, you can't add const

12, explicit keyword

Modifying the constructor with explicit will prohibit the implicit conversion of single parameter constructor, as shown in the following figure

13, static member

Concept: class members declared as static are called static members of the class, and member variables modified with static are called static member variables; The member function modified with static is called static member function

characteristic

Static members are shared by all class objects and do not belong to a specific instance. For example, the static member variable count is initialized to 0. In object d1, it is added once to 1. In object d2, it is still 1 and will not be 0

Static member variables must be defined and initialized outside the class without adding the static keyword

Class static members are available class names: static members or objects Static members to access

Static member functions have no hidden this pointer and cannot access any non static members. They can only access static member variables and static member functions, but non static member functions can call static member functions

Like ordinary members of a class, static members have three access levels: public, protected and private, and can also have return values

14, A new method of member initialization in C++11

C++11 supports the initialization and assignment of non static member variables during declaration. The purpose is to solve the problem of calling its default constructor initialization for user-defined variables before, and make a patch instead of dealing with built-in types

Note: here is the default value for the declared member variable, not initialization!

15, Friends

Friends are divided into friend functions and friend classes

Disadvantages of friends: increase the coupling degree, destroy the package, and should not be used more

friend function

A friend function can directly access the private members of a class. It is an ordinary function defined outside the class and does not belong to any class, but needs to be declared inside the class. When declaring, you need to add the friend keyword

Friend functions can access private and protected members of a class, but not member functions of a class

Friend functions cannot be modified with const

Friend functions can be declared anywhere in the class definition and are not limited by the class access qualifier

A function can be a friend function of multiple classes

The calling principle of friend function is the same as that of ordinary function

Friend class

All member functions of a friend class can be friend functions of another class and can access non-public members of another class

Friend relations are unidirectional and not exchangeable

For example, if class A and class B declare class B as its friend class in class A, you can directly access the private member variables of class A in class B, but you can't access the private member variables of class B in class A

  

Friend relationship cannot be passed

If B is a friend of a and C is a friend of B, it does not mean that C is a friend of A

16, Inner class

Concept: if a class is defined inside another class, this inner class is called an inner class

The internal class B is basically the same as the global definition, except that it is limited by the external class a domain and is defined in the class domain of A

Internal class B is naturally a friend of external class A, that is, B can access a's private, and a cannot access B's private

characteristic

Internal classes can be defined in public, protected and private of external classes

The internal class can directly access the static and enumeration members in the external class without the object / class name of the external class

Sizeof (external class) = external class, which has nothing to do with internal class

//Header file

#pragma once
#include<iostream>
using namespace std;
class Date
{
	friend ostream& operator<<(ostream& out,const Date& d);
	friend istream& operator>>(istream& in, Date& d);
public:
	//Constructor
	Date(int year = 1970, int month = 1, int day = 4);
	//Find the number of days of each month
	int GetMonthDay(int _year, int _day)const;
	//Print date
	void Print() const;
	//Compare date size
	bool operator>(const Date& d2) const;
	bool operator<(const Date& d2) const;
	bool operator==(const Date& d2) const;
	bool operator>=(const Date& d2) const;
	bool operator<=(const Date& d2) const;
	bool operator!=(const Date& d2) const;
	//Find the date after how many days
	Date& operator+=(int day);
	Date operator+(int day) const;
	//How many days ago
	Date& operator-=(int day);
	Date operator-(int day) const;
	//Pre + +, post++
	Date& operator++();
	Date operator++(int);
	//Front and rear--
	Date& operator--();
	Date operator--(int);
	//How many days is the difference between the two dates
	int operator-(const Date& d2);
	//Date assignment
	Date& operator=(const Date& d2);
	//Ask for the day of the week
	void WeekDay();
private:
	int _year;
	int _month;
	int _day;
};

//Definition file

#include"date.h"

int Date::GetMonthDay(int _year, int _month)const
{
	static int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = arr[_month];
	if (_month == 2 && ((_year % 4 == 0 && _year % 100 != 0) || (_year % 400 == 0)))
	{
		day += 1;
	}
	return day;
}

void Date::Print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
	if (!(_year > 0 && (_month > 0 && _month < 13) && (_day > 0 && _day <= GetMonthDay(_year,_month))))
	{
		cout << "Illegal date" << endl;
		Print();
	}
}

bool Date::operator>(const Date& d2)const
{
	if (_year > d2._year)
	{
		return true;
	}
	else if (_year == d2._year && _month > d2._month)
	{
		return true;
	}
	else if (_year == d2._year && _month == d2._month && _day > d2._day)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool Date::operator<(const Date& d2)const
{
	return !(*this >= d2);
}

bool Date::operator==(const Date& d2)const
{
	return _year == d2._year && _month == d2._month && _day == d2._day;
}

bool Date::operator>=(const Date& d2)const
{
	return *this > d2 || *this == d2;
}

bool Date::operator<=(const Date& d2)const
{
	return !(*this > d2);
}

bool Date::operator!=(const Date& d2)const
{
	return !(*this == d2);
}

Date& Date::operator+=(int day)
{
	if (day < 0)
	{
		return *this -= -day;
	}
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		++_month;
		if (_month == 13)
		{
			_month = 1;
			++_year;
		}
	}
	return *this;
}

Date Date::operator+(int day) const
{
	Date ret(*this);
	ret += day;

	return ret;
}

Date& Date::operator-=(int day)
{
	if (day < 0)
	{
		return *this += -day;
	}
	_day -= day;
	while (_day <= 0)
	{
		--_month;
		if (_month == 0)
		{
			_month = 12;
			--_year;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}

Date Date::operator-(int day) const
{
	Date ret(*this);
	ret -= day;

	return ret;
}

Date& Date::operator++()
{
	*this += 1;
	return *this;
}

Date Date::operator++(int)
{
	Date ret(*this);
	*this += 1;

	return ret;
}

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}

Date Date::operator--(int)
{
	Date ret(*this);
	*this -= 1;

	return ret;
}

int Date::operator-(const Date& d2)
{
	Date max = *this;
	Date min = d2;
	int flag = 1;//Default D1 > D2
	if (*this < d2)
	{
		max = d2;
		min = *this;
		flag = -1;
	}
	int count = 0;
	while (min != max)
	{
		++min;
		++count;
	}
	return flag * count;
}

Date& Date::operator=(const Date& d2)
{
	_year = d2._year;
	_month = d2._month;
	_day = d2._day;

	return *this;
}

void Date::WeekDay()
{
	Date d(1900, 1, 1);
	const char* arr[7] = { "Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday" };
	int count = (*this) - d;
	cout << arr[count % 7] << endl;
}

ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
	return out;
}

istream& operator>>(istream& in, Date& d)
{
	in >> d._year>> d._month>> d._day;
	return in;
}

//Test file

#include"date.h"

void test1()
{
	Date d1(2021, 2, 9);
	Date d2(2021, 2, 9);
	cout << (d1 > d2) << endl;
	cout << (d1 < d2) << endl;
	cout << (d1 <= d2) << endl;
	cout << (d1 >= d2) << endl;
	cout << (d1 == d2) << endl;
	cout << (d1 != d2) << endl;
}

void test2()
{
	Date d1(2022, 1, 30);
	d1 += 1500;
	d1.Print();

	Date d2(2020, 1, 15);
	d2 -= 1500;
	d2.Print();
}

void test3()
{
	//Date d1(2022, 3, 15);
	//Date d2(2016, 1, 19);
	//int ret = d1 - d2;
	//cout << ret;

	//cout << d1;
	//cout << d2;
	//Date d3;
	//cin >> d1;
	//cout << d1;
	//cout << d3;

	/*Date d1;
	cin >> d1;*/
	/*Date d1;
	cin >> d1;
	cout << d1;*/

	Date d1(2022, 2, 25);
	d1.WeekDay();
}
int main()
{
	//test1();
	//test2();
	test3();
	return 0;
}

Keywords: C++ Back-end

Added by Cory94bailly on Sat, 19 Feb 2022 15:19:51 +0200