Yue Wang
Yue Wang

Reputation: 1750

Is it a good practise to put non member function inside a class?

I'm reading a 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 never saw this way before. Is it a good practice to define nonmember function inside a class body with friend? Any pros and cons?

Upvotes: 3

Views: 1882

Answers (3)

Tony Delroy
Tony Delroy

Reputation: 106244

Is it a good practice to define nonmember function inside a class body with friend?

Indifferent practice, I'd say.

Any pros and cons?

Pros

  • the operators can refer to class members (nested classes, typedefs, enums, constants, static functions etc.) in the class's scope without needing to explicitly prefix them with the class name

  • it's convenient to have the streaming functions implicitly inline - no One Definition Rule hassles

  • friendship means you can access all the non-public members conveniently

  • people studying the class source code are more likely to notice the streaming capabilities

  • as Mike Seymour commented, if the class is a template then defining a friend lets you omit the template <...> aspect of the operators, and refer to the instance argument simply as a const Member& rather than a const Member<...>&.

Cons

  • you may want an out-of-line function definition so you can modify the implementation later and only need to relink (rather than recompile) client code

  • you're granting friendship that might not have been functionally necessary, that lessens encapsulation and therefore maintainability

  • people looking for a non-member streaming operator might not think to look in the class code

  • you could argue it "clutters up" the class definition source code, making it harder to take in the totality of the actual class members

As usual, the benefits of clean separation of interface and implementation - both for managing physical dependencies (the need to recompile rather than just relink) and for human readability - tends to increase for low level libraries used by disparate higher level libraries and applications, and be far lower for "private" support of local implementation (e.g. a class in an anonymous namespace in a .cpp file, used only by that single translation unit, or - even more so - a private nested class).

Upvotes: 5

James Kanze
James Kanze

Reputation: 154047

In general, it's not good practice; ideally, the implementation wouldn't even be in the same file as the class definition. (Ideally, too, we wouldn't have to declare the private parts in the header file either.) There are a lot of justified exceptions, however:

  • The most obvious is in really simple helper classes, where there really isn't enough to justify separating both parts. This is especially true if the helper class is defined locally, in the source file, rather than in a header.

  • Another case is for friends, particularly in templates. If I write (even in a template) friend void f( MyClass& ), then I have declared a non-template to be friend, and I have to implement a separate non-template function for each instantiation type. If I provide the inline implementation in the class definition, however, the compiler will automatically create the separate non-template function for each type it is used. This is a very frequent motivation for definition operator>> and operator<< in the class, as they cannot be members; often they will be declared as friend even if they don't need access to private members, just so that they can be defined this way.

Finally, if there are no other declarations of the functions or operators, they are only visible within the class, or with ADL. Which shouldn't be a problem, as long as the function has at least one parameter which involves the class.

Upvotes: 4

Raoul Steffen
Raoul Steffen

Reputation: 556

Possible Pro: Easier to read and maintain, if you have all or most other functions handling the class' private members defined inside the class body as well. It keeps things together.

Con: Functions defined in the class body appear in every compilation unit instead of just one compiling the respective .cpp file you could put them in instead.

Upvotes: 1

Related Questions