C++ meta inner class anonymous object

Youyuan

  You can break through the encapsulation by using the element, and you can directly access the private member functions of the class, etc., and provide traversal at a certain time, but the increased coupling destroys the encapsulation, so it is recommended not to use the element more.

The so-called coupling is that the closer the relationship between two things, the greater the coupling. In fact, if we want to achieve encapsulation, a close relationship is not a good result.

There are functions

Use the friend keyword  in the class  to modify an ordinary function outside the class (this function does not belong to any class), that is, use the friend keyword to declare in the class and define it outside the class, then this function is a friend of this class Metafunction , this function can access the private members of this class.

 As in the following example, because the first parameter of the member function is the this pointer of the corresponding object, then if we define an overloaded operator in the class, the first parameter must be the this pointer of the object, then we are calling this When using a function, the variable on the left can only be an object. For example, if we overload "<<", then we can only write d1 << cout in this way. If cout << d1, an error will be reported.

But the first way is not our usual writing habit, so we think of defining it outside the class, and then in order for this "<<" overloaded function to be able to access the members of the class, we can use this overloaded operator function, Declaring it as a metafunction means that this function is a friend of this class, so this function can access its private members.

 Defined in the class:

class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
	// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
	ostream & operator<<(ostream& _cout)
	{
		_cout << _year << "-" << _month << "-" << _day << endl;
		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

 Defined outside the class:

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;
}

【Notice】:

  •  Metafunctions can access private protected members, but not member functions.
  • A metafunction cannot be decorated with const, because it cannot be defined in a class, and there is no this pointer.
  • Metafunctions can be declared anywhere in the class, not restricted by class access qualifiers
  • A function can interact with multiple classes
  • Calling a metafunction is the same as calling an ordinary function

 metaclass

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

 【Notice】:

  •  Metaclasses are one-way. For example, class D1 is a metaclass of class D2, then class D1 can access its member functions, etc., but D2 cannot access member functions in D1.
  • You cannot transfer. For example, C is a member of B, and B is a member of A, but C is not a member of A.
  • A meta-relationship cannot be inherited.
class A
{
	friend class B;
public:
	int Get_a()
	{
		return _a;
	}
protected:
	int _a = 1;
};

class B
{
public:
	int GetA_a()
	{
		// 直接访问 A类当中的私有成员
		return a._a;
	}
protected:
	int _b = 0;
	A a;

};

inner class

 The class defined in the class is the inner class of this class. This inner class is a class. There is no way to access the private members of the inner class through the outer class, that is to say, the inner class does not belong to the outer class .

 Let's first calculate the size of class A in the following code:

 We found that it is 4, this 4 only calculates the size of the member _a, because _b in A is static, we say that the only members in the class are just declarations, and the definition is in the object, but the static members are not stored In the object, it is defined globally. The same is true for class B in class A. There is no B object in A, so the size of B is not calculated. If we define the object B in a member of A then the size is 8:

 The difference between the above-mentioned class B defined outside class A and class B defined in class A is that the former is defined in the global domain, while the latter is defined in the class domain of A.

To put it vividly, if the class is a drawing and the object is the house to be built, then like the above-mentioned B is the internal class of A, there is no space for class B among the objects of class A we create, and it is in the house of A at this time Put B's drawing.

So since it is defined in the class domain of A, then this class B can access the private members of class A, that is, the inner class is the friend class of the outer class. But the outer class is not a friend of the inner class.

class A
{
public:

	class B
	{
	public:
		int GetA_a()
		{
			return a._a;
		}

	protected:
		int _b = 0;
		A a;
	};

protected:
	int _a = 1;
	static int _b;
	B b;
};
  • 1. The inner class can be defined as public, protected, or private in the outer class.
  • 2. Note that the inner class can directly access the static members of the outer class without the object/class name of the outer class.
  • 3. sizeof (external class) = external class, has nothing to do with the inner class
     

 Only those defined are restricted by the access qualifier, and the above is only a statement, so it will not be restricted.

 anonymous object

class A
{
public:
	int Get_a()
	{
		return _a;
	}
protected:
	int _a;
};

int main()
{
	// 匿名创建对象
	A();
}

As mentioned above, an object is created using an anonymous object.

Use an anonymous object to call a member function:

int main()
{
	// 匿名创建对象
	A().Get_a();
}

We can use this method to call the member function of the class once, if it is multiple times, then we have to use the normal way of creating objects to call the member function.

The reason for saying this is that anonymous objects are destroyed when they are used .

The life cycle of a named object is in the function local area , and the life cycle of an anonymous function is in the current line .

 【Notice】:

We can't call member functions like this:

A::Get_a();

The premise of calling this way is that this function is static, and if calling this function like this, there must be no this pointer. And member functions must have this pointer.

Anonymous objects are as constant as temporary objects , so we cannot create ordinary references to anonymous objects:

 So you need to add a const to compile:

	const A& pa = A();

And when we use const to refer to this anonymous object, the life cycle of this anonymous object will be extended, and the extended time is the life cycle of the reference.

 As in the following example:

class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}

	int Get_a()
	{
		return _a;
	}
protected:
	int _a;
};

class AAAAAAAAA
{
public:
	AAAAAAAAA()
	{
		cout << "AAAAAAAAA()" << endl;
	}

	~AAAAAAAAA()
	{
		cout << "~AAAAAAAAA()" << endl;
	}
};

int main()
{

	const A& pa = A();

	AAAAAAAAA aaaaaaaa;
}

We print the constructor and destructor of the two classes as long as they have been called, indicating that this function is called, let's look at the output:

 We found that the anonymous function A() is destroyed after the object AAAAAAAAA() is destroyed.

 Usage scenarios of anonymous functions:

void Print_string(const string& st)
{
	cout << st << endl;
}

int main()
{
	string str("11111");  // 1
	Print_string(str);    // 2

	return 0;
}

The codes 1 and 2 above can be written in one line using anonymous objects:

Print_string(string("11111"));

At this point, an anonymous object is used for parameter passing.

Guess you like

Origin blog.csdn.net/chihiro1122/article/details/130613818