I'm trying to understand a code snippet that I've managed to make work by trial and error. I understand everything about this snippet except why it doesn't work when I take "friend" out of the class declaration. I don't understand what friend is doing in this context.
stringstream log;
class logWrapper {
friend ostream& operator<<(ostream& os, logWrapper& thislogend)
{
stringstream &ss = dynamic_cast(os);
// This line replaced with printf for clarity
// The actual code sends the C style string to a
// legacy logging system that only takes C style strings
// _log(LOG_ERR, "%s", ss.str().c_str());
printf("%s\n", ss.str().c_str());
ss.str("");
return os;
}
} logend;
int main(void)
{
log << "This is a test" << logend;
}
When the function is declared as a friend, then it can access the private and protected data members of the class. A friend function is declared inside the class with a friend keyword preceding as shown below.
A friend function is a non member function or ordinary function of a class, which is declared as a friend using the keyword “friend” inside the class. By declaring a function as a friend, all the access permissions are given to the function.
A friend function in C++ is a function that is declared outside a class but is capable of accessing the private and protected members of the class. There could be situations in programming wherein we want two classes to share their members.
Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions. Like member inline functions, they behave as though they were defined immediately after all class members have been seen, but before the class scope is closed (at the end of the class declaration).
You are simultaneously declaring and defining a friend function, which overloads an operator.
Functions which are declared as friend
can access all the private members of any instance of the class which befriended them.
This is different from regular member functions (which can obviously also access private members), since friend functions are not members of the class -- they are stand-alone functions.
So since you've defined the stand-alone function inside the class, it appears confusing at first glance -- just remember that it's not really a member function at all.
It means that the friend is not a member of the class, but you can access static
class members and member types (including private
ones) without qualification.
This makes the function "look and feel" like a member. Because operator<<
here is intimately tied to the logWrapper
, it is intuitive that you can implement it as if it were a member of the class.
But remember, it is not a member! It is just a free function with special access privileges, just as if it were defined outside.
Edit: Since there are no static members and no member types, this happens not to make a difference here. You could move the definition of the friend outside without changing it. This style is idiomatic, though, because you could. Often it is used with templates, which often do have member types/typedefs.
Indeed, defining a friend inside a template<…> class
block is the only way to define a templated non-template function. This esoteric and sometimes-elusive beast is nonetheless sometimes very convenient to have around. Usually his creation is accidental, even serendipitous, so I won't get into that discussion…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With