Reputation: 183
As the question asks...
What is the difference between:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
private:
int m_a;
friend void set_a(MyClass &a);
};
void set_a(MyClass &a)
{
std::cout << a.m_a << std::endl;
a.m_a = 500;
std::cout << a.m_a << std::endl;
}
int main(void) {
MyClass my_class_instance;
set_a(my_class_instance);
system("pause");
}
and:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
void set_a(){
std::cout << this->m_a << std::endl;
this->m_a = 500;
std::cout << this->m_a << std::endl;
}
private:
int m_a;
};
int main(void) {
MyClass my_class_instance;
my_class_instance.set_a();
system("pause");
}
Is it simply the preferred structure of the function, or are there real, measurable differences? From what I can tell, both functions achieve the same results in all circumstances, except if you had multiple overloads for the first example, that took different types of objects.
Upvotes: 0
Views: 1044
Reputation: 14174
As the C++ FAQ says: Use a member when you can, and a friend when you have to.
There are situations where making friend
a free function is preferable, most situations related to the fact that the first parameter of a member function is always of that class (Its the hidden *this
parameter).
One example is arithmetic operators overloading:
Suppose you write a complex
class which represents complex numbers. Using a member operator+()
you could write expressions like complex + float
, but not float + complex
. But you could do it with the free form of the operator+
:
class complex
{
...
friend complex operator+( float f , complex c );
};
Upvotes: 4
Reputation: 8972
Many people defend that making accessor methods, you can in a later stage of development put barriers to the incorrect access to the member variables (or even change the member variables totally) without breaking your (correct) clients.
One classical case is of a
class ComplexNumber {
double real, imaginary;
public:
double re() { return re; }
double setRe(double v) { return re = v; }
// and so on ...
};
one day you discover, in some maintenance, that you need the polar coordinates for that number, so you add the methods
double rho() { /* calculate rho */ }
double theta() { /* calculate theta */ }
double setRho(double v) { /* calculate real, imaginary, based on the new rho */ }
and so on.
Later yet, you discover that the users of the class use far more often polar than Cartesian coordinates for complex numbers, and that the conversions have been the bottleneck of a performance problem, so you ditch real
and imaginary
and store rho
and theta
, and change the getter and setter methods for the new -- more efficient -- storage for rho
, theta
, re
, im
, and so on. All the clients of your class will recompile without problems, because you changed your implementation but kept your interfaces stable.
Upvotes: 0
Reputation: 27538
This whole question comes down to "Why would I use friends in C++?". The answer is that when used properly, friends enhance encapsulation. This is an FAQ:
Do friends violate encapsulation?
Your example is too short and too abstract, of course. Some better, real life examples I could think of from the top of my head involve iterators. You may have many iterator objects referring to only one container object, and you may want the iterator to be able to access private member variables of the container. At the same time, you don't want the container to expose those variables to the rest of the world.
Such a design could be perfectly implemented with the friend
feature.
Upvotes: 2