C++: initialization list, static members, friends, inner classes

Insert image description here

Personal homepage: Personal homepage
Personal column: "Data Structure" "C Language" "C++"


Preface

This blog serves as a knowledge summary of C++: initialization list, static members, friends, and internal classes.


1. Initialization list

Initialization list: Begins with a colon, followed by a comma-separated list of data members, each "member variable" followed by an initial value or expression in parentheses.
Insert image description here


  • The initialization list is where each member variable is defined
  • Each member variable can only appear once in the initialization list, that is, the member variable of each object can only be defined once.

Insert image description here
Insert image description here


  • Reference member variables , const member variables , and custom type members (those without default constructors) must be initialized in the initialization list location.
class B
{
    
    
public:
	B(int b)
		:_b(b)
	{
    
    }

private:
	int _b;
};

class A
{
    
    
public:
	A(int a, int& i)
		:_a(a) // const成员变量
		,_reti(i)// 引用类型成员变量
		,_b(1)//  自定义类型成员
	{
    
    }

private:
	const int _a;
	int& _reti;

	B _b;
};

For const member variables, reference member variables must be initialized and assigned when they are defined. Custom type members will call the corresponding default constructor when they are defined. If there is no default constructor, they need to explicitly call the corresponding constructor when they are defined, and the initialization list This is where the object's member variables are defined.


  • Constructor initial value assignment and initialization list initialization are mixed

Insert image description here


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

  • The order in which member variables are declared in a class is the order in which they are initialized in the initialization list, regardless of their order in the initialization list.

What is the result of the following program?

class A
{
    
    
public:
	A(int a)
		:_a1(a)
		,_a2(_a1)
	{
    
    }

	void Print()
	{
    
    
		cout << "_a1 = " << _a1 << endl;
		cout << "_a2 = " << _a2 << endl;
	}

private:
	int _a2;
	int _a1;
};

int main()
{
    
    
	A a(1);
	a.Print();

	return 0;
}

Insert image description here
This is because the order of initialization of member variables is related to the order of member declaration. We declare member variable a2 first, and then declare member variable a1. Then in the initialization member list, we first execute _a2(_a1). At this time, _a1 is a random value, so in the printed result, _a1 is 1 and _a2 is a random value.


Note: C++11 supports declaring default values ​​for member variables. This default value is used in the initialization list.

2. static members

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

Question: Implement a class and count the number of class objects being used in the program

class A
{
    
    
public:
	A()
	{
    
    
		_count++;
	}

	A(const A& a)
	{
    
    
		_count++;
	}

	~A()
	{
    
    
		_count--;
	}

	int get_count()
	{
    
    
		return _count;
	}
private:
	static int _count;
};

int A::_count = 0;

Here we need to use static member variables, _count++ every time the constructor and copy constructor are called, and _count– every time the destructor is called.


  • Static members are shared by all class objects and do not belong to a specific object. They are stored in the static area.

What is the size of class A below?

class A
{
    
    
private:
	static int i;
};

int main()
{
    
    
	cout << sizeof(A) << endl;

	return 0;
}

Insert image description here
The size of class A is 1, which is the empty class.

  • Static member variables must be defined outside the class. The static keyword is not added when defining. It is just declared in the class.
  • Class static members can be accessed using class name::static member or object.static member

Insert image description here

  • Static member functions have no hidden this pointer and cannot access any non-static members.

Insert image description here

Insert image description here

  • Static members are also class members and are restricted by public, protected, and private access qualifiers.

Insert image description here
Insert image description here
If you want to access the static member i, you can implement functions such as Geti() to access it.
Insert image description here

3. Youyuan

Friends are divided into friend functions and friend classes

Friend functions
For example, when we want to overload the << operator for the date class, we will find that operator<< cannot be overloaded as a member function because the implicit this pointer occupies the first parameter position of the operator<< function. In this way, the overloaded << operator cannot be used normally.
Insert image description here

Insert image description here
Of course we can use d << cout like this, but isn’t it a bit weird?
In this case, we need to overload operator<< into a global function, but when it becomes a global function, the member variables of the object cannot be accessed. At this time, a friend class is needed to solve it (it can also be solved using the GetYear / GetMonth / GetDay function).

A friend function can directly access the private members of a class. It is an ordinary function defined outside the class. It does not belong to any class, but is declared inside the class. The friend keyword needs to be added when declaring it.

class Date
{
    
    
	friend ostream& operator<<(ostream& _cout, const Date& d);

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

private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
    
    
	_cout << d._year << "/" << d._month << "/" << d._day;

	return _cout;
}
int main()
{
    
    
	Date d(2023, 9, 16);
	cout << d;

	return 0;
}

Insert image description here

  • Friend functions can access private and protected members of a class, but not member functions of the class
  • Friend functions cannot be modified with const
  • Friend functions can be declared anywhere in a class definition and are not restricted by class access qualifiers.
  • A function can be a friend function of multiple classes
  • The calling principle of friend functions is the same as that of ordinary functions.

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.

  • The friend relationship is one-way and not commutative.
    It is as follows: B is a friend class of A. Class B can access the member variables of class A, but class A cannot access the member variables of class B.
    Insert image description here
    Insert image description here

  • Friend relationships cannot be transferred

  • Friend relationships cannot be inherited

4. Internal classes

Inner class: If a class is defined inside another class, this class is called a left inner class. The inner class is an independent class. It does not belong to the outer class, and the members of the inner class cannot be accessed through the objects of the outer class.

Insert image description here
As shown in the figure: B is the internal class of A

Note: Inner classes are friend classes of outer classes. The inner class can access all members of the outer class through the object parameters of the outer class, but the outer class is not a friend of the inner class.

  • Inner classes can be defined in public, protected, private of the outer class
  • The inner class can directly access the static members in the outer class without the need for an object of the outer class. and class name::
class A
{
    
    
public:
	class B
	{
    
    
	public:
		void func(const A& a)
		{
    
    
			cout << i << endl;
			cout << a._a << endl;
		}
	};

	A()
	:_a(0)
	{
    
    }
private:
	static int i;
	int _a;
};

int A::i = 0;

int main()
{
    
    
	A::B b;
	b.func(A());
	return 0;
}

Insert image description here

  • sizeof(external class) = external class, has nothing to do with internal class
class A
{
    
    
public:
	class B
	{
    
    
	private:
		int _b;
	};

	A()
	:_a(0)
	{
    
    }
private:
	static int i;
	int _a;
};

What is the size of the above class?
Insert image description here


Summarize

The above is a summary of my knowledge about initialization lists, static members, friends, inner classes, and anonymous objects. Thanks for the support! ! !
Insert image description here

Guess you like

Origin blog.csdn.net/li209779/article/details/132904310