c++ Friend函数在类中不可见

n7taea2i  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(134)

我有以下代码:

struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

Live example
g++4.8和clang3.4都无法编译它,因为fM中不可见,或者他们说的。
然而,该标准给出了类似代码的示例

class M {
  friend void f() { } // definition of global f, a friend of M,
                      // not the definition of a member function
};

并说
在类中定义的friend函数在定义它的类的(词法)作用域中。
(ISO/IEC 14882:2011 11.3 Friends [class.friend] p6,p7)
从这一点上,我不能理解编译器如何无法找到f,这是在同一个类中定义的,它的使用。
两个编译器不太可能有相同的bug。
我错过了什么

x6yk4ghg

x6yk4ghg1#

友元声明声明周围命名空间中名为f的函数是类的友元;但是它没有将名称f引入到名称空间中。在命名空间中声明它之前,它是不可用的(除了依赖于参数的查找)。
相关规则是C++11 7.3.1.2/3:
如果非局部类中的friend声明首先声明了一个类或函数,则友元类或函数是最内层封闭命名空间的成员。**通过非限定查找或限定查找,**无法找到朋友的名字,直到在该命名空间范围内提供匹配的声明。

gv8xihay

gv8xihay2#

关键的问题是在什么情况下编译器能够/允许找到你的函数声明。对于一个通用的friend函数,你必须在类的外部声明它,这样编译器才能找到它。
但有一个非常有用的例外:如果friend函数有一个类类型的参数,由于argument-dependent name lookup,它可以在没有额外声明的情况下找到该函数。
这种情况实际上非常重要,因为通常您希望friend函数访问类类型的对象。
请考虑以下示例:

#include <iostream>

struct M
{
    friend void printI(int a) {
        std::cout << a;
    }
    friend void print(const M& m) { // friend takes object of class type!
        std::cout << "M";
    }
    void foo() {
        printI(2); // ERROR - requires declaration!
        print(*this); // OK!
    }
};

int main()
{
    M m;
    m.foo();
    printI(2); // ERROR - requires declaration!
    print(m); // OK
}
ttvkxqim

ttvkxqim3#

C++标准中的这句话
在类中定义的友元函数在定义它的类的(词法)作用域中。
意味着以下
9在授予友谊的类中内联定义的朋友函数(11.3)的定义中使用的名称的名称查找应按照成员函数定义中的查找所述进行。
也就是说,从类作用域开始搜索函数中使用的任何名称。
但是,函数本身在命名空间中不可见,直到它在类外部声明。
所以在你的例子中,在类定义之前声明函数就足够了

void f() {}

struct M {
    friend void f();
    M() {
        f(); 
    }
};

int main() {
    M m;
}

void f();

struct M {
    friend void f() {}
    M() {
        f(); 
    }
};

int main() {
    M m;
}
olmpazwi

olmpazwi4#

struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

上面的代码工作得很好。(在DevC++上尝试)也尽量不要在类内部定义函数,因为它可能没有外部作用域,即。在main()中。在尝试从main()调用f()时,您将收到一个错误,说函数不存在。因此,使用::操作符(如果需要)在类外部定义函数,以便从任何地方访问函数都没有问题。Access friend function defined in class

相关问题