But why would I make a public member function a friend if it already has access to private data memmbers?
I presume that making a function global does two things:
1. It can no longer access private data members
2. If it is an overloaded function, it can now "magically" deal with left hand operands that are not user-defined (I say 'magically' because I don'tunderstand how this happens, I just know that it does)
Are either of those presumptions incorrect (as I suspect they are)?
A public member function of another class doesn't have access to your private members (unless you make it your friend)
non-member functions are just that, functions. They aren't a part of any class.
The left hand operands thing has to do with operator overloading, not just functions in general: functions in general don't have "left hand" or "right hand" operands. They take a comma-separated list of arguments.
When overloading operators for a user-defined class, you have a choice (for most of them) between implementing them as members or as non-members. Non-member forms accept your class on either side, member forms only on the left.
So let's say I have two classes - teacher and student. And let's say I want each teacher object to be able to generate a curve for the grades on an exam, let's say, and as such the teacher class needs to access the private data members that contain the students' grades. In this case, I assume a friend function would be appropriate.
Is that the kind of situiation in which friend functions would be useful? And if so, what exact function do I make a friend?
Yes, that almost sounds like a plausible use case, although to be realistic, the teacher wouldn't be asking each student secretly what their grades were, he probably owns those grades since the exam. Also, friending your Teacher would give him access to more than just your grade, he'd be able to touch everything. Friend classes and functions are pretty rare in design, because they give too much access.