Let's imagine that I have an object a (of type Rational) and a function to fill that rational (write its numerator and denominator members). Well, I have two options:
MAIN PROGRAM
#include <iostream>
#include "Racional.h"
using namespace std;
int main()
{
Racional a, b;
cout << "Sumar dos numeros racionales" << endl;
cout << "RELLENA PRIMER RACIONAL: " << endl;
//OPCION A:
rellenarRacional(a); //Aquí envío el objeto a por referencia
//OPCION B:
a.rellenarRacional(); //Aquí aplico la función sobre el objeto a
}
FUNCTION DEFINITION FOR OPTION A:
void rellenarRacional(Racional& r)
{
cout << "Introduce el numerador del racional: " << endl;
cin >> r.numerador;
cout << Introduce el denominador del racional: " << endl;
cin >> r.denominador;
}
FUNCTION DEFINITION FOR OPTION B:
void Racional::rellenarRacional()
{
cout << "Introduce el numerador del racional: " << endl;
cin >> numerador;
cout << "Introduce el denominador del racional: " << endl;
cin >> denominador;
}
Could you help me see the differences between the two? When should I use one and when another? Because as far as I read, the best option is B in this program.
Thank you very much and greetings.
It is preferable to use free functions and that are not friends (non-member, non-friend) before member functions. (For the case: your option A)
Also, there is a famous earlier article, also by Scott Meyers, at http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
I think that basically the ideas that support this statement are the Object Orientation Principles that indicate that data should be kept as encapsulated as possible.
The most natural way for the author is to put these "utilities" in the same namespace as the class, thus offering them as part of the class interface, and which can be extended by adding other functions to the same namespace, even in files. separated, in the same way that it is done in the STL.
independent function
This version has two drawbacks:
friend
)The main advantage is that it doesn't overload the class interface.
member function
This function is basically the opposite of the previous option:
Racional
When to choose one or the other?
Well, it depends on each case.
As a general rule we could say that if the functionality to be covered is intrinsic to the object, for example a method that paints a geometric object in a scene, the functionality should be implemented in the class itself. Also, since I'm not a fan of using it
friend
except in completely justified cases, if the function needs to access protected or private methods, it should be a member function.On the other hand, if the functionality is accessory or certain design patterns are used (for example, the decorator pattern), it may be interesting to implement independent functions.
But there are no written rules on when to opt for one mechanism and when for another.
Grades:
1 After reading other published answers, I think it is convenient to explain this point so as not to create confusion. In fact, in C++ a function can be overloaded as many times as you want:
But these free functions can cause problems when working with polymorphism:
This situation will not occur in the case of member functions as long as they are marked as virtual:
To the excellent answers from eferion and asdasdasd I would like to add some more information.
In general terms it is considered that the use of free functions (your Option A) is a more flexible and generic solution since it can take advantage of function overloading , C++ stl takes advantage of this with
std::begin
andstd::end
of the header<iterator>
:Fundamental types do not have member functions, so it is not possible to get an iterator from an array 1 by calling the member function
begin
, since it does not have one:It could be said that free functions (your Option A) is C++'s way of offering a kind of extension methods like those of C#, with the difference that they are not called as a member function (your Option B) but as a free function . This is precisely the focus of technical document N4165 written by Herb Sutter 2 (my translation):
You can read the rest of the document (in English) at the link I provided earlier. There he explains in more detail the pros and cons of calls to free functions (your Option A) and member functions (your Option B), whitepaper N4165 was a proposal for C++17 that was never introduced, it proposed to unify the two call syntaxes to be mutually compatible.
Conclusion.
My opinion is that no option is better than the other, you should choose one or the other based on the needs of your project.