Is it good practice to use the non member function inside a class?
I am reading code like this:
class Member
{
public:
friend std::istream& operator>>(std::istream& in, Member& m)
{
in >> m.name >> m.bYear >> m.bMonth;
return in;
}
friend std::ostream& operator<<(std::ostream& out,const Member& m)
{
out << m.name << " " << m.bYear << "." << m.bMonth;
return out;
}
private:
std::string name;
int year;
int month;
};
I've never seen this before. Is it good practice to define a memberless function inside the body of the c class friend
? Any pros and cons?
source to share
Is it good practice to define a nonmember function inside a class body with a friend?
Indifferent practice, I would say.
Any pros and cons?
Pros
-
operators can refer to class members (nested classes, typedefs, enums, constants, static functions, etc.) in the class scope without the need to explicitly prefix them with the class name
-
convenient to have streaming functions implicitly
inline
- no One Definition Rule hassles -
Friendship means you can easily access all non-public users
-
people examining the source code of a class are more likely to notice the streaming capabilities
-
commented Mike Seymour, if the class is a template that allows the determination of other lower aspect
template <
...>
operators and refer to an instance of an argument just likeconst Member&
notconst Member<
...>&
.
Against
-
you may need to define a function off the net so that you can modify the implementation later and only need to reconfigure (not recompile) the client code
-
you provide a friendship that might not be functionally necessary, which reduces encapsulation and therefore maintainability
-
people looking for a non-streaming operator may not think about how to look in the class code
-
you could argue that it "clutters" the source code of the class definition, making it harder for the totality of the actual members of the class.
As usual, the benefits of a clean separation of interface and implementation - both for managing physical dependencies (needing to recompile, not just rewriting) and for human readability - tend to increase for low-level libraries used by scattered higher-level libraries and applications and be much below to support local implementation (w700) (for example, a class in an anonymous namespace in a file .cpp
that is only used by that single translation unit, or even more so a nested class private
).
source to share
In general, this is not good practice; ideally the implementation will not even be in the same file as the class definition. (Ideally, too, we would not need to declare private parts in the header file.) There are many justifiable exceptions:
-
The most obvious one is a really simple helper class, where it really isn't enough to justify separating both parts. This is especially true if the helper class is defined locally in the source file and not in the header.
-
Another thing for friends, especially in templates. If I write (even in a template)
friend void f( MyClass& )
then I have declared that non-template is a friend and I have to implement a separate non-template function for each instance type. If I provided an inline class definition, however, the compiler will automatically generate a separate function without a template for each type used. This is a very common motivation for definitionoperator>>
andoperator<<
in the classroom, since they cannot be members; often they will be declared asfriend
even though they do not need access to private members so that they can be defined that way.
Finally, if there are no other function statements or operators, they are only visible within the class or with ADL. This shouldn't be a problem as long as the function has at least one parameter that includes the class.
source to share
Perhaps Pro: Easier to read and maintain if you have all or most of the other functions handling the private members of a class defined inside the body of the class. He keeps things together.
Con: The functions defined in the class of the class appear in every compilation unit, not just to compile the corresponding .cpp file you could add them to.
source to share