C++ - 必须在头文件中定义好友函数吗?

Pac*_*ane 12 c++ operator-overloading friend header-files

我想在我的一个类中重载operator <<.签名是这样的:

friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj)
Run Code Online (Sandbox Code Playgroud)

当我尝试在.cpp文件中定义它时,它表示运算符<<确切地接受1个参数,但是,当我在.h中定义它时,它编译/工作正常.

这是我在.cpp文件中定义它的方式:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... }
Run Code Online (Sandbox Code Playgroud)

是否与需要在头文件中定义的朋友功能有关?

Xeo*_*Xeo 13

它可以在cpp文件中定义,但至少需要在头文件中声明,否则你想要使用它的所有地方只会看到流本身给你的东西,而不是你的重载.

// .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
}
Run Code Online (Sandbox Code Playgroud)


rua*_*akh 9

问题在于你定义它的方式.它不是班上的成员,它只是班上的朋友.你需要删除Annuaire::前缀.所以,改变这个:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ...
Run Code Online (Sandbox Code Playgroud)

对此:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ...
Run Code Online (Sandbox Code Playgroud)

错误消息的原因是Annuaire::operator<<(std::ostream& os, const Annuaire& obj)需要三个参数:Annuaire它被调用的实例(as this),以及另外两个参数(osobj).


小智 5

正如David的回答中提到的,在这种情况下,运算符不是成员函数,它只是同一名称空间中的友元函数.这使我指出了解决非常类似问题的正确方向.

我发布这个答案是因为它对我来说并不是很明显.也许是因为我添加运算符的实现文件没有完全包含在命名空间中,而是使用了using-directive.

不应该是相关的,但我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)