c++必须在头文件中定义友元函数

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

本文关键字:定义 友元 函数 文件 c++      更新时间:2023-10-16

我想重载操作符<<在我的一节课上。签名是这样的:

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

当我试图在。cpp文件中定义它时,它说操作符<<确切地接受一个参数,但是,当我在。h中定义它时,它编译/工作正常。

我在。cpp文件中是这样定义的:

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

它与需要在头文件中定义的友元函数有关吗?

可以在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
}

问题在于你定义它的方式。它不是类的成员,它只是类的好友。需要去掉Annuaire::前缀。所以,修改这个:

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

:

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

错误消息的原因是Annuaire::operator<<(std::ostream& os, const Annuaire& obj)期望有三个参数:它被调用的Annuaire实例(作为this),以及两个额外的参数(osobj)。

正如David的回答中提到的,在这种情况下,操作符不是成员函数,它仅仅是同一名称空间中的友元函数。这给我指明了解决类似问题的正确方向。

我把这个答案贴出来是因为它对我来说不是很明显。也许是因为我添加运算符的实现文件没有完全包含在命名空间中,而是使用了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;
}

友元函数,即使它们看起来是在类内部声明的,也不是成员函数,而是命名空间级函数(在封闭的命名空间中)。在代码中,正确地声明了友元函数,但尝试将其定义为类的成员函数:

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

该定义适用于具有两个实参的Annuaire成员函数operator<<,由于operator<<可以通过以下两种方式重载:作为具有两个实参(左侧和右侧)的自由函数,或者作为具有rhs类型实参的类的成员函数出现在表达式的lhs中。在这个特殊的例子中,由于lhs是std::ostream,您不能修改它,因此您只能选择使用一个自由函数:

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

无此限制;你可能只是写错了。应该是这样的:

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;
}