[classes and objects] initialization list, friends, static members, internal classes


Hello, bald men. Today, let's continue to talk about classes and objects

Key points of this chapter

  1. Initialization list
  2. Friends
  3. static member
  4. Inner class
  5. Understand encapsulation again

Let's talk about constructors

After studying the first two chapters [classes and objects], let's take a look at the structure

Constructor body assignment

When creating an object, the compiler calls the constructor to give each member variable in the object an appropriate initial value

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
private:
	int _year;
	int _month;
	int _day;
};

Although there is an initial value in the object after the above constructor call, it cannot be called initialization of class object members. 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

Initialization list

class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};

be careful

  1. Each member variable can only appear once in the initialization list (initialization can only be initialized once)
  2. Class contains the following members, which must be placed in the initialization list for initialization
    1. Reference member variable
    2. const member variable
    3. Custom type member (this class has no default constructor)
class A
{
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a;
};


class B
{
public:
	B(int a, int ref)
		:_a(a)
		, _ref(ref)
		, _n(10)
	{}
private:
	A _a; // There is no default constructor
	int& _ref; // quote
	const int _n; // const
};

To sum up:
1. The initialization list is where the member variable is defined
2. const, reference, custom type member variables without default constructor must be initialized in the initialization list, because they must be initialized at the time of definition
3. For built-in types such as int, it is optional, but try to complete initialization in the initialization list

Last point:
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

explicit keyword

Constructors can not only construct and initialize objects, but also have the function of type conversion for constructors with single parameters

class Date
{
public:
	Date(int year)
		:_year(year)
	{}
	explicit Date(int year)
		:_year(year)
	{}
private:
	int _year;
	int _month;
	int _day;
};
void TestDate()
{
	Date d1(2022);
	// Assign a value to a date type object with an integer variable
	// The actual compiler will construct an unnamed object with 2022, and finally assign a value to d1 object with an unnamed object
	d1 = 2022;//This is equivalent to an implicit type conversion
}

The essence of d1=2022 is to construct a nameless temporary object with 2022. Date(2022) copies and constructs the temporary object to d1, but the c + + compiler will optimize the continuous construction and combine the two into one, so this is just a simple construction.

The above code: modifying the constructor with explicit will prohibit the implicit conversion of single parameter constructor

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. Static member variables must be initialized outside the class.

class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	static int GetACount() { return _scount; }
private:
	static int _scount;
};
int A::_scount = 0;
int main()
{
	cout << A::GetACount() << endl;//0
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;//3
	return 0;
}

characteristic:

  1. Static members are shared by all class objects and do not belong to a specific instance
  2. Static member variables must be defined outside the class without adding the static keyword
  3. Class static members are available class names: static members or objects Static members to access
  4. Static member functions have no hidden this pointer and can only access static member variables and member functions
  5. There are three types of members that can be accessed statically and have the same level as the members of the protected class and the public class

A new method of member initialization in C++11

C++11 supports initialization and assignment of non static member variables during declaration, but it should be noted that this is not initialization, but the default value of declared member variables.

class A
{
public:
	A()
	{}
private:
	int _a1 = 0;
	B _b1 = 10;
	B _b2 = B(20);
	int* p = (int*)malloc(4 * 10);
	int arr[10] = { 1,2,3,4,5 };
};

Friends

Friends are divided into: friend function and friend class

Friends provide a way to break through encapsulation, sometimes providing convenience. However, friends will increase the degree of coupling and destroy the package, so friends should not be used more.

friend function

Problem: now we try to overload operator < < and find that we can't overload operator < < into member functions. Because the output stream object of cout and the implied this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, which is the left operand. However, in actual use, cout needs to be the first formal parameter object before it can be used normally. So we need to overload operator < < into a global function. But in this case, there will be no way to access members outside the class, so we need friends to solve it. The same goes for operator > >.

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.

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year=1, int month=0, int day=0)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
ostream& operator<<(ostream& out, const Date& d)
{
	out << d._year << "-" << d._month << "-" << d._day;
	return out;
}
istream& operator>>(istream& in, Date& d)
{
	in >> d._year >> d._month>> d._day;
	return in;
}
int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

explain:

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

1. Friend relations are unidirectional and not exchangeable
2. Friend relationship cannot be passed

class Date
{
    friend class Time;
};

The above code: time is a friend class of Date. Time can access your Date, but Date cannot access time

Inner class

class A
{
public:
    class B
    {
    };
};

Above code:
1. The internal class B is basically the same as that defined globally, except that it is limited by the external class A domain, which is A::B bb.
2. The size of sizeof(A) does not include class B.
3. Inner class B is naturally a friend class of outer class A, that is, B can access a's private, while a cannot access B's private.

Understand encapsulation again

C + + is an object-oriented program. Object-oriented has three characteristics: encapsulation, inheritance and polymorphism.

Through classes, C + + combines the attributes and behaviors of an object to make it more in line with people's cognition of a thing, and packs all the things belonging to the object together; Through the access qualifier, some of its functions are selectively opened to interact with other objects. For some implementation details inside the object, external users do not need to know, and it is useless in some cases. On the contrary, it increases the difficulty of use or maintenance and complicates the whole thing.
This is the meaning of encapsulation

Object oriented is actually simulating the abstract mapping of the real world

⭐ Thanks for reading. I'll see you next time
If there is any mistake, welcome to communicate with us

Keywords: C++ Algorithm data structure Interview

Added by incubi on Sat, 05 Mar 2022 07:32:39 +0200