C++ friend functions and friend classes (C++ friend keyword)

Posted by cbj4074 on Wed, 02 Feb 2022 14:59:32 +0100

C++ friend functions and friend classes (C++ friend keyword)

In C + +, a class can have members of public, protected and private attributes. Public members can be accessed through objects, and only functions in this class can access private members of this class. Now let's introduce an exception - friend. With the help of friends, member functions in other classes and functions in the global scope can access the private members of the current class.

Friend means friends, or friends. The relationship with friends is obviously closer than that of ordinary people. We will open our hearts to our good friends and tell our secrets, while we will be cautious about our words and deeds to ordinary people and protect ourselves subconsciously. In C + +, this kind of friendly relationship can be indicated by the keyword friend, which is often translated into "friend" in Chinese. With the help of friends, you can access the private members of the class with which you have a friend relationship. If you are not used to the term "friend", you can understand friend as a friend according to the original text.

friend function

Functions defined outside the current class and not belonging to the current class can also be declared in the class, but the friend keyword should be added in front of them to form a friend function. Friend functions can be non member functions that do not belong to any class or member functions of other classes.

Friend functions can access all members in the current class, including the public, protected and private attributes.

1) Declare a nonmember function as a friend function.

Please look directly at the following example:

#include <iostream>
using namespace std;
class Student{
public:
    Student(char *name, int age, float score);
public:
    friend void show(Student *pstu);  //Declare show() as a friend function
private:
    char *m_name;
    int m_age;
    float m_score;
};
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
//Nonmember function
void show(Student *pstu){
    cout<<pstu->m_name<<"What is your age "<<pstu->m_age<<",The result is "<<pstu->m_score<<endl;
}
int main(){
    Student stu("Xiao Ming", 15, 90.6);
    show(&stu);  //Call friend function
    Student *pstu = new Student("Li Lei", 16, 80.5);
    show(pstu);  //Call friend function
    return 0;
}

Operation results:

Xiao Ming's age is 15 and his grade is 90.6
 Li Lei's age is 16 and his grade is 80.5

Show () is a global non member function. It does not belong to any class. Its function is to output Student information. m_name,m_age,m_score is a private member of the Student class. In principle, it cannot be accessed through an object, but these private members must be used in the show() function. Therefore, show() is declared as a friend function of the Student class. Readers can test it by themselves, delete line 8 in the above program and observe the error message of the compiler.

Note that the friend function is different from the member function of the class. The member of the class cannot be accessed directly in the friend function, and the object must be used. The following wording is wrong:

void show(){
    cout<<m_name<<"What is your age "<<m_age<<",The result is "<<m_score<<endl;
}

When a member function is called, it will implicitly add this pointer to the object calling it, so as to use the members of the object; show() is a non member function without this pointer. The compiler does not know which object member to use. To make this clear, you must pass the object through parameters (you can pass the object directly, or pass the object pointer or object reference), and specify the object when accessing the member.

2) Declare member functions of other classes as friend functions

The friend function can be not only a global function (non member function), but also a member function of another class. Take the following example:

#include <iostream>
using namespace std;
class Address;  //Declare the Address class in advance
//Declare Student class
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};
//Declare the Address class
class Address{
private:
    char *m_province;  //province
    char *m_city;  //city
    char *m_district;  //District (urban area)
public:
    Address(char *province, char *city, char *district);
    //Declare the member function show() in the Student class as a friend function
    friend void Student::show(Address *addr);
};
//Implement Student class
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"What is your age "<<m_age<<",The result is "<<m_score<<endl;
    cout<<"Home address:"<<addr->m_province<<"province"<<addr->m_city<<"city"<<addr->m_district<<"area"<<endl;
}
//Implement the Address class
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}
int main(){
    Student stu("Xiao Ming", 16, 95.5f);
    Address addr("Shaanxi", "Xi'an", "Yan pagoda");
    stu.show(&addr);
   
    Student *pstu = new Student("Li Lei", 16, 80.5);
    Address *paddr = new Address("Hebei", "Hengshui", "Taocheng");
    pstu -> show(paddr);
    return 0;
}

Operation results:

Xiao Ming's age is 16 and his grade is 95.5
 Home address: Yanta District, Xi'an City, Shaanxi Province
 Li Lei's age is 16 and his grade is 80.5
 Home address: Taocheng District, Hengshui City, Hebei Province

This example defines two classes, Student and Address. On line 27 of the program, the member function show() of Student class is declared as a friend function of Address class. Therefore, show() can access the private member variable of Address class.

Some notes:

① In line 4 of the program, the Address class is declared in advance because it was used in the Student class before the definition of the Address class. If it is not declared in advance, the compiler will report an error and prompt 'Address' has not been declared. The advance declaration of classes and functions is the same.

② The program separates the declaration and implementation of the Student class, and puts the declaration of the Address class in the middle. This is because the compiler compiles the code from top to bottom. The show() function body uses the members of Address, province, city and district. If you don't know the specific declaration of Address in advance, It is not possible to determine whether Address owns the member (the class declaration indicates which members the class has).

Here is a brief introduction to the advance declaration of classes. In general, classes can only be used after formal declaration; However, in some cases (as shown in the above example), you can also use it first as long as you make a declaration in advance.

However, it should be noted that the scope of use of class advance declaration is limited. Only after a class is formally declared can it be used to create objects. If the following statement is added after line 4 of the above program, the compiler will report an error:

Address addr;  //An attempt was made to create an object with an incomplete class

Because memory is allocated to the object when it is created, the compiler cannot determine how much memory should be allocated to the object until the class is formally declared. The compiler can only determine how much memory should be reserved for the object after "seeing" the formal declaration of the class (actually seeing member variables). After a class is declared in advance, you can use the name of the class to define the pointer variable (this example defines the pointer variable of the Address class) or reference variable (reference will be introduced later), because the size of the pointer variable and reference variable itself is fixed, regardless of the size of the data it points to.

③ A function can be declared as a friend function by multiple classes, so that private members in multiple classes can be accessed.

Friend class

Not only can a function be declared as a "friend" of a class, but also the whole class can be declared as a "friend" of another class, which is a friend class. All member functions in a friend class are friend functions of another class.

For example, if class B is declared as a friend class of class A, all member functions in class B are friend functions of class A and can access all members of class A, including public, protected and private attributes.

Change the code of the above example and declare the Student class as a friend class of the Address class:

#include <iostream>
using namespace std;
class Address;  //Declare the Address class in advance
//Declare Student class
class Student{
public:
    Student(char *name, int age, float score);
public:
    void show(Address *addr);
private:
    char *m_name;
    int m_age;
    float m_score;
};
//Declare the Address class
class Address{
public:
    Address(char *province, char *city, char *district);
public:
    //Declare the Student class as a friend of the Address class
    friend class Student;
private:
    char *m_province;  //province
    char *m_city;  //city
    char *m_district;  //District (urban area)
};
//Implement Student class
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){ }
void Student::show(Address *addr){
    cout<<m_name<<"What is your age "<<m_age<<",The result is "<<m_score<<endl;
    cout<<"Home address:"<<addr->m_province<<"province"<<addr->m_city<<"city"<<addr->m_district<<"area"<<endl;
}
//Implement the Address class
Address::Address(char *province, char *city, char *district){
    m_province = province;
    m_city = city;
    m_district = district;
}
int main(){
    Student stu("Xiao Ming", 16, 95.5f);
    Address addr("Shaanxi", "Xi'an", "Yan pagoda");
    stu.show(&addr);
   
    Student *pstu = new Student("Li Lei", 16, 80.5);
    Address *paddr = new Address("Hebei", "Hengshui", "Taocheng");
    pstu -> show(paddr);
    return 0;
}

The code in line 24 declares the Student class as a friend class of the Address class. The declaration statement is:
friend class Student;

Some compilers can also not write the class keyword, but it is recommended to write it in order to enhance compatibility.

There are two points to note about friends:

The relationship between friends is one-way rather than two-way. If it is declared that class B is a friend class of class A, it does not mean that class A is a friend class of class B. the member function in class a cannot access the private member in class B.

The relationship between friends cannot be passed. If class B is a friend class of class A and class C is a friend class of class B, it does not mean that class C is a friend class of class A.

Unless necessary, it is generally not recommended to declare the whole class as a friend class, but only some member functions as friend functions, which is safer.

Topics: C++ Back-end