>C++>Friends and Internal Classes

1. Friends

Friends provide a way to break through encapsulation and sometimes provide convenience. Friends, however, increase the coupling and destroy the encapsulation, so they should not be used more often.
Friends are divided into: Friend Functions and Friend Classes

1.1 Friend Function

Problem: Now try to overload operator<<, and find that there is no way to overload operator< as a member function. Because the output stream object of the cout and the implicit this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, the left operand. However, in practice, cout needs to be the first parameter object in order to work properly. So overload operator < as a global function. However, it will cause members to be inaccessible outside of the class, which needs a friend to solve. Operator > the same. (

class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	// D1 << cout; -> D1.operator< (&d1, cout); Non-conforming call
	// Because the first parameter of a member function must be hidden this, d1 must be placed to the left of <.
	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

friend functions have direct access to private members of a class. They are common functions defined outside the class and do not belong to any class. They need to be declared inside the class, with the friendly keyword added.

class Date
{
	friend ostream& operator<<(ostream& _cout, const Date& d);
	friend istream& operator>>(istream& _cin, Date& d);
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _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;
}
istream& operator>>(istream& _cin, Date& d)
{
	_cin >> d._year;
	_cin >> d._month;
	_cin >> d._day;
	return _cin;
}
int main()
{
	Date d;
	cin >> d;
	cout << d << endl;
	return 0;
}

Explain:

  • Friend functions access the private and protected members of a class, but are not member functions of the class
  • Friend functions cannot be const-modified
  • 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
  • Friend functions are called in the same way as normal functions

1.2 Friend Class

All member functions of a friend class can be friend functions of another class, and non-public members of another class can be accessed. (

class Time
{
	friend class Date; // Declaring a date class as a friend of the time class directly accesses the private member variables in the Time class in the date class
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)
	{
		// Direct access to time class private member variables
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
  • Friend relationship is one-way and not exchangeable.

For example, if you declare the Date class as its friend class in the Time class, you can access the private member variables of the Time class directly in the Date class, but you cannot access the private member variables of the Date class in the Time class.

  • Friendship cannot be transferred

If C is the friend of B and B is the friend of A, then the friend of A at C cannot be explained. (

  • Friendship cannot be inherited

2. Internal Classes

Concept: If a class is defined inside another class, the internal class is called the internal class. An internal class is a separate class. It does not belong to an external class, nor can it access its members through its objects. External classes do not have any superior access to internal classes.

Note: An internal class is a friend class of an external class. See the definition of a friend class. An internal class can access all members of an external class through its object parameters. But the external class is not a friend of the internal class. (

class A
{
private:
	static int k;
	int h;
public:
	class B // B is by nature the friend of A
	{
	public:
		void foo(const A& a)
		{
			cout << k << endl;//OK
			cout << a.h << endl;//OK
		}
	};
};
int A::k = 1;
int main()
{
	A::B b; // External classes need to be specified when creating objects with internal classes
	b.foo(A());
	return 0;
}

Characteristic:

1. public, protected, private are all possible for internal classes to be defined on external classes.
2. Note that internal classes have direct access to static members in external classes and do not require object/class names of external classes.
3. sizeof = external class, has nothing to do with internal class.

class A
{
	int _a;
	int _b;
	class B 
	{
		int _c;
	};
};

int main()
{
	cout << sizeof(A) << endl; //Sizeof = external class, has nothing to do with internal class
	return 0;
}

Mind Mapping

 

 

Tags: C++ Back-end programming language

Posted by billshackle on Fri, 16 Sep 2022 21:36:45 +0530