[C++ Elementary] Friends of Classes and Objects (Part 2) + Inner Classes + Anonymous Objects

Personal homepage: @Weraphael
? About the author: Currently learning C++ and algorithms
Column: C++ Airway
I hope you will support us a lot, and we will make progress together!
If the article is helpful to you
Welcome to comment Like Favorite Add concern?

Table of Contents

  • 1. Friends
    • 1.1 Friend functions
      • 1.11 Friend function features
      • 1.12 Why Friends are Not Recommended
    • 1.2 Friend class
      • 1.21 Features of friend classes
  • Second, the inner class
    • 2.1 Characteristics of inner classes
  • 3. Anonymous objects
    • 3.1 Characteristics of anonymous objects

1. Friends

Friends provide a way to break encapsulation. Friends are divided into: friend function and friend class.

1.1 Friend function

We used friend functions when implementing the date class. When overloading operator<<, it is found that there is no way to overload operator<< into a member function, because the first parameter of a member function is usually a this pointer. while cout's
The output stream object and the implicit this pointer are preempting the position of the first parameter. The this pointer defaults to the first parameter, which is the left operand. But in actual use, cout needs to be the first formal parameter object to be used normally. Therefore, operator<< can only be overloaded as a global function. But this will lead to no way to access members outside the class, and friends are needed to solve it. operator>> is the same.

#include <iostream>
using namespace std;

class Date
{<!-- -->
public:
// friend statement
// (The following two functions can use member variables in the class)
friend istream & amp; operator>>(istream & amp; cin, Date & amp; x);
friend ostream & amp; operator<<(ostream & amp; cout, const Date & amp; x);

private:
int Year;
int Month;
int Day;
};

istream & amp; operator>>(istream & amp; cin, Date & amp; x)
{<!-- -->
cin >> x.Year >> x.Month >> x.Day;
return cin;
}

ostream & amp; operator<<(ostream & amp; cout, const Date & amp; x)
{<!-- -->
cout << x.Year << "Year" << x.Month << "Month" << x.Day << "Day";
return cout;
}

int main()
{<!-- -->
Date d1;
cin >> d1;
cout << d1 << endl;

return 0;
}

[Result display]

1.11 Friend function features

  1. Friend functions can access private and protected members of a class, but not member functions of the class

This is because the member function is called through the object of the class, and the object must be present to call the member function. The friend function does not belong to the member function of the class, so it cannot directly access the member function of the class.

  1. Friend functions cannot be modified with const

A friend function is defined outside the class and it can access the private members of the class. The const keyword means that the member function will not modify the state of the object, but the friend function is not bound to any object, nor is it subject to class access control, so const modifier has no meaning for friend functions.

  1. Friend functions can be declared anywhere in the class definition, not restricted by class access qualifiers
  2. A function can be a friend function of multiple classes
  3. The principle of calling a friend function is the same as that of a normal function

1.12 Why is friend not recommended

  • First of all, friends break the principle of encapsulation: it exposes the implementation details of the class to the outside, increasing the complexity and difficulty of the code.
  • The friendship relationship is one-way. If you need to access the private members of multiple classes, you need to make a friend declaration in each class, which will increase the difficulty of code maintenance.
  • Finally, friends destroy the inheritance relationship of classes, and subclasses cannot inherit the friendship relationship in the base class, thus limiting the maintainability and scalability of the code.
  • Therefore, while friends can be convenient in some cases, in general they are not recommended.

1.2 Friend class

#include <iostream>
using namespace std;

class 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)
{<!-- -->
// Directly access the private member variables of the time class
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int_year;
int_month;
int_day;
Time_t;
};

The above code declares the friend class of the Date class in the Time class, and then directly accesses the Time class in the Date class strong>

1.21 Features of friend classes

  1. The friendship relationship is one-way and not exchangeable.

For example, the above Time class and Date class, declare Date class as its friend class in the Time class, then You can directly access the private member variables of the Time class in the Date class, but want to access the Date in the Time class Private member variables in the class are not allowed

  1. Friendship cannot be passed

If C is a friend of B, and B is a friend of A, it cannot explain C is a friend of A.

  1. Friend relationship cannot be inherited

2. Inner class

If a class is defined inside another class, the inner class is called an inner class.

#include <iostream>
using namespace std;

class A
{<!-- -->
public:
// B is an inner class of A
class B
{<!-- -->
public:
void foo(const A & a)
{<!-- -->
\t\t\t
}
};
private:
static int k;
int h;
};
// How to define static member variables
int A::k = 1;

2.1 Characteristics of inner classes

  1. The inner class can be defined in public, protected, private of the outer class.
  2. The inner class is an independent class, it does not belong to the outer class, note: You cannot access the members of the inner class through the object of the outer class. Outer classes do not have any privileged access to inner classes
  3. But The inner class is the friend class of the outer class. The inner class can access all members of the outer class through the object parameter of the outer class. (In short, the inner class can access all members of the outer class, but the outer class cannot). And the inner class can directly access the static members of the outer class, without the object/class name of the outer class
#include <iostream>
using namespace std;

class A
{<!-- -->
public:
A(int i = 3)
:h(i)
{<!-- -->

}
// B is an inner class of A
class B
{<!-- -->
public:
void foo(const A & a)
{<!-- -->
// Inner classes can directly access static members in outer classes
cout << k << endl;
// Inner class can access all members of outer class
cout << a.h << endl;
}
};
private:
static int k;
int h;
};
// How to define static member variables
int A::k = 1;

int main()
{<!-- -->
A a1;
A::B b; //Definition of inner class
\t
b. foo(a1);

return 0;
}

[Procedure Results]

  1. sizeof(outer class) = outer class, has nothing to do with inner class
#include <iostream>
using namespace std;

class A
{<!-- -->
public:
A(int i = 3)
:h(i)
{<!-- -->

}
// B is an inner class of A
class B
{<!-- -->
public:
void foo(const A & a)
{<!-- -->
// Inner classes can directly access static members in outer classes
cout << k << endl;
// Inner class can access all members of outer class
cout << a.h << endl;
}
};
private:
static int k;
int h;
};
// How to define static member variables
int A::k = 1;

int main()
{<!-- -->
cout << sizeof(A) << endl;

return 0;
}

[Procedure Results]

Note: Member variables modified by static do not need to be calculated. Because static member variables belong to the class, each object belonging to the class is shared, and does not belong to a specific object, and is stored in the static area.

3. Anonymous object

Features of Anonymous Objects No Name

#include <iostream>
using namespace std;

class A
{<!-- -->
public:
\t// Constructor
A(int i)
:a(i)
{<!-- -->
cout << "call constructor" << endl;
}
// destructor
~A()
{<!-- -->
cout << "call destructor" << endl;
}
private:
int a;
};

int main()
{<!-- -->
A(2); // anonymous object
A a(1); // named object
\t
return 0;
}

But The life cycle of an anonymous object is only one line, we can see that it will automatically call the destructor in the next line, and the declaration cycle of the famous function is the local domain of the current function.

3.1 Characteristics of anonymous objects

  1. Anonymous objects have constant properties

  1. const refers to an anonymous object, and its life cycle is the same as that of a named object: the local scope of the current function

A(2) will first call the copy construction, and then print "call construction" on the screen, and then due to type conversion, a temporary variable will be generated in the middle, and the temporary variable also has constant properties. Then the temporary variable is copied and constructed to x. So, this should call construction twice, why is it only called once? The reason is: For this kind of continuous construction, the compiler will directly optimize and use direct construction to improve efficiency.

syntaxbug.com © 2021 All Rights Reserved.