Part Two of Classes and Objects (Easy to Understand)


Preface

This article mainly explains the main contents of advanced constructors, static members, friends and inner classes!


1. Advanced constructor:

1.Default constructor:

Default constructor: No parameters need to be passed in when calling it. There are three types: no parameters, full default constructor, and the one automatically generated by the compiler without explicit writing by the user.

class Date
{
    
    
public:
	Date()
	{
    
    
		_year = 2022;
		_month = 8;
		_day = 28;
	}
	Date(int year = 2022, int month = 8, int day = 28)//1
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

Note: Although the above two parameters-free and full-default can constitute function overloading, they will cause ambiguity. When you define an object without passing parameters for initialization, the compiler will not be clear about the overloaded function call.

After understanding what the default structure is, let’s look at this code:
This code willreport an error, but why? ? ?

class B
{
    
    
public:
	B(int b)
	{
    
    
		_b = b;
	}
private:
	int _b;
};
class A
{
    
    
public:
	A(int x, int y)
	{
    
    
		_a = x;
		B b(y);
		_b = b;
	}
private:
	int _a;
	B _b;
};
int main()
{
    
    
	A a1(10, 20);
	return 0;
}

Because when an object of type A calls the constructor for initialization, because there are custom type members of type B, the default constructor in class B will be called, but in class B There is no default constructor, so an error will be reported!

Solution: You can add a default constructor in class B to solve the problem.
Insert image description here
But this will cause a problem. The constructor will first go to class B to call its default structure and then return to the constructor body of class A to continue executing the code in the function. It also needs to execute the function again. Only one copy construction and assignment in the body can achieve the desired effect, which seems very cumbersome. Is there any way to make it more convenient?

The C++ initialization list solves this problem very well:

2.Initialization list:

Initialization list: Starts with a colon, followed by a comma-separated list of the remaining data members, each "member variable" followed by an initial value or expression in parentheses.

class B
{
    
    
public:
	B(int b)
	{
    
    
		_b = b;
	}
private:
	int _b;
};
class A
{
    
    
public:
	A(int x, int y)
		:_a(x)
		,_b(y)
	{
    
    }
private:
	int _a;
	B _b;
};

Precautions:

  1. Each member variable can only appear once in the initialization list (initialization can only be initialized once).
  2. Try to use an initialization list for initialization, because no matter whether you use an initialization list or not, custom type member variables must be initialized using an initialization list first.
  3. The class contains the following members, which must be placed in the initialization list for initialization:
  • const member variables.
  • Reference member variables.
  • Custom type members (and the class does not have a default constructor.

3.explicit keyword:

Insert image description here
Why is it written like the picture above?
The constructor can not only construct and initialize objects, but also has the function of type conversion for a single parameter or a constructor that has default values ​​except for the first parameter.

The above code is very poorly readable. Modifying the constructor with explicit can prohibit implicit conversion of the constructor.

class A
{
    
    
public:
	explicit A(int a)
		:_a(a)
	{
    
    }
private:
	int _a;
};
int main()
{
    
    
	A a1 = 10;
	return 0;
}

2. static members:

1.Basic concepts:

Class members declared as static are called static members of the class. Member variables modified with static are called static member variables; member functions modified with static are called static member functions.

Note: Static member variables must be initialized outside the class

class A
{
    
    
public:
	A(int a)
		:_a(a)
	{
    
    }
private:
	int _a;
	static int _n;
};
int A::_n = 20;
int main()
{
    
    
	A a1(10);
	return 0;
}

2. Features:

  • Static member variables must be defined outside the class. The static keyword is not added when defining. It is just declared in the class.
  • Static members are shared by all class objects, do not belong to a specific object, and are stored in the static area.
  • Class static members can be accessed using classname::static member or object.static member.
  • Static member functions have no hidden this pointer and cannot access any non-static members.
  • Static members are also members of the class and are restricted by public, protected, and private access qualifiers.

3. Friends:

Friends provide a way to break through the encapsulation. Although it provides convenience, it destroys the encapsulation and is not suitable for multiple uses.

1. Friend function:

Let’s first look at a piece of code that overloads the << operator:

class Date
{
    
    
public:
	Date(int year = 2022, int month = 8, int day = 28)//1
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
	ostream& operator<<(ostream& out)
	{
    
    
		out << _year << "-" << _month << "-" << _day << endl;
		return out;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
    
    
	Date d1(2022, 1, 1);
	//cout << d1;//error
	d1 << cout;//?????
	return 0;
}

When you perform operator overloading on <<, because cout is the left operand when used normally, you will find that the implicit this pointer of will inevitably occupy the left operand. The position of causes your cout to have to be the second parameter. So at this time, we can onlyoverload it into a global function, but overloading into a global function will affect theprivate members in the class. Can't access again. At this timefriend function plays an important role!

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. However, it needs to be declared inside the class. The friend keyword needs to be added when declaring.

class Date
{
    
    
	friend ostream& operator<<(ostream& out, const Date& date);
	friend istream& operator>>(istream& in, Date& date);
public:
	Date(int year = 2022, int month = 8, int day = 28)//1
	{
    
    
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};
//因为成员函数默认this在第一个,所以<<写成全局函数,用友元函数访问私有成员
ostream& operator<<(ostream& out, const Date& date)
{
    
    
	out << date._year << "-" << date._month << "-" << date._day << endl;
	return out;
}

istream& operator>>(istream& in, Date& date)
{
    
    
	in >> date._year >> date._month >> date._day;
	return in;
}
int main()
{
    
    
	Date d1(2022, 1, 1);
	cin >> d1;
	cout << d1 << endl;
	return 0;
}

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

class Time
{
    
    
	// 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
	friend class Date; 
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{
    
    }
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
    
    
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{
    
    }
	void SetTimeOfDate(int hour, int minute, int second)
	{
    
    
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};

Notice:

  1. Friend relationships are one-way and non-commutative. For example, the above-mentioned Time class and Date class, declare the Date class as its friend class in the Time class, then you can directly access the Time in the Date class
  2. Private member variables of the class, but if you want to access the private member variables of the Date class in the Time class, you cannot. Friend relationships cannot be transferred
  3. If C is a friend of B and B is a friend of A, it cannot mean that C is a friend of A. Friend relationships cannot be inherited.

4. Internal classes:

Concept: **If class B is defined inside class A, class B is called the internal class of class A. **The inner class does not belong to any class, and the outer class does not have any superior rights over the inner class.

Note: The inner class is naturally a friend class of the outer class, but the outer class is not a friend class of the inner class.

Features:

  1. Inner classes can be defined as public, protected, or private in external classes.
  2. Note that inner classes can directly access static members in outer classes without requiring the object/class name of the outer class.
  3. sizeof(external class)=external class, has nothing to do with internal classes.

Summarize

The above is the content of the next part of classes and objects that I will talk about today. I hope it will be helpful to you who have just read this blog!

Guess you like

Origin blog.csdn.net/weixin_61661271/article/details/126569068