C++ - must friend functions be defined in the header file?

27,774

Solution 1

It can be defined in a cpp file, but it needs to at least be declared in a header file, otherwise all places where you want to use it will only see the stuff the stream itself gives you, not your overload.

// .h and in class
friend std::ostream& operator<<(std::ostream& os, MyClass const& v);

// .cpp
std::ostream& operator<<(std::ostream& os, MyClass const& v){
    // print it
}

Solution 2

The problem is with the way you're defining it. It's not a member of the class, it's just a friend of the class. You need to drop the Annuaire:: prefix. So, change this:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ...

to this:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ...

The reason for the error message is that Annuaire::operator<<(std::ostream& os, const Annuaire& obj) would expect three arguments: the Annuaire instance that it's called on (as this), and and two additional arguments (os and obj).

Solution 3

As mentioned in David's answer, in this case the operator is not a member function, it is merely a friend function in the same namespace. This pointed me in the right direction in solving a very similar issue.

I'm posting this answer because it wasn't immediately obvious to me. Maybe because the implementation file where I was adding the operator wasn't fully enclosed in the namespace, and used a using-directive instead.

Shouldn't be relevant but I'm using VS2013.

//Foo.h
namespace Bar{
    class Foo
    {
    public:
        Foo();
    private:
        int n;
        friend std::ostream & operator<<(std::ostream &, Foo const &);
    };
}

//Foo.cpp
using namespace Bar; //won't apply to the operator definition
Foo::Foo(){}// doesn't require the Bar qualifier because of the using-directive

//the operator required the Bar namespace qualifier
std::ostream & Bar::operator<<(std::ostream & o, Foo const & x)
{
    return o << x.n;
}

Solution 4

Friend functions, even if they seem to be declared inside the class are not member functions but rather namespace level functions (in the enclosing namespace). In your code you declare the friend function correctly, but you try to define it as a member function of the class:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){

That definition would be for a member function of Annuaire, called operator<<, that takes two arguments, which is invalid as operator<< can be overloaded in one of two ways: as a free function taking two arguments (left hand side and right hand side) or as a member function of the class that appears in the lhs of the expression taking an argument of the rhs type. In this particular case, since the lhs is std::ostream and you cannot modify it, you are left with the only option of using a free function:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj)

Solution 5

No such restriction; you're probably just writing it wrong. Should be something like this:

class Foo
{
   int n;

   friend std::ostream & operator<<(std::ostream &, Foo const &);
};

std::ostream & operator<<(std::ostream & o, Foo const & x)
{
   return o << x.n;
}
Share:
27,774
Pacane
Author by

Pacane

wat?

Updated on July 11, 2022

Comments

  • Pacane
    Pacane almost 2 years

    I want to overload the operator << in one of my classes. The signature goes like this:

    friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj)
    

    When I try to define it in the .cpp file it says that the operator<< exactly takes 1 argument, however, when I define it in the .h, it compiled/works fine.

    This is how I define it in the .cpp file :

    std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... }
    

    Does it have anything to do with friend functions needing to be defined in header files?

  • moooeeeep
    moooeeeep over 11 years
    +1 for adding a note on the enclosing namespace. To add using namespace X before the actual function definition is not enough.
  • Flynsee
    Flynsee over 7 years
    Exactly my problem! I'm not too sure why this is happening though.