If a member function of a class has to fully access an object of another class, we can make that member function friend of another class.
For example, let’s say we have two classes File and Saver. File stores an int and Saver saves the File using save member function. save requires private member access of File, so we made save a friend of File.
#include <iostream>
class File;
class Saver
{
public:
Saver() = default;
void save(const File &file);
};
class File
{
int m_data{};
public:
File() = default;
File(int data) : m_data{data} {}
friend void Saver::save(const File &file);
};
void Saver::save(const File &file)
{
std::cout << "Saving File with content: " << file.m_data << "\n";
}
int main(int argc, char const *argv[])
{
File f{1};
Saver{}.save(f);
return 0;
}The order of definitions here is critical for compilation. First, Saver must be fully defined before File declares its member function as a friend, because the friend declaration references Saver::save by qualified name—the compiler needs to know that Saver exists and has a save member function.
Second, the implementation of Saver::save must appear after File’s complete definition, since the function body accesses File’s private member m_data—the compiler requires the full class layout to validate this access.