首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >朋友函数在类中不可见。

朋友函数在类中不可见。
EN

Stack Overflow用户
提问于 2014-05-08 11:42:39
回答 4查看 2.8K关注 0票数 11

我有以下代码:

代码语言:javascript
复制
struct M {
    friend void f() {}
    M() {
        f(); // error: 'f' was not declared in this scope
    }
};

int main() {
    M m;
}

实例化

g++4.8和clang3.4都无法编译它,因为fM中是不可见的,或者他们这么说。

但是,标准给出了一个类似代码的示例

代码语言:javascript
复制
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之友class.friend p6,p7)

由此,我无法理解编译器如何找不到在使用它的同一个类中定义的f

这两个编译器不太可能有相同的bug。

我错过了什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-05-08 12:01:41

friend声明指出,在周围的名称空间中名为f的函数是类的朋友;但是它没有将名称f引入名称空间。在命名空间中声明之前,它是不可用的(依赖于参数的查找除外)。

相关规则是C++11 7.3.1.2/3:

如果非本地类中的friend声明首先声明一个类或函数,则朋友类或函数是最内部的封闭命名空间的成员。朋友的名字不通过非限定查找或限定查找找到,直到在该命名空间范围中提供匹配声明为止。

票数 12
EN

Stack Overflow用户

发布于 2014-05-08 11:59:19

这是来自C++标准的引用

在类中定义的朋友函数位于定义它的类的(词法)范围内。

表示以下内容:

9.在授予友谊的类中定义的朋友函数(11.3)的定义中使用的名称查找应按照成员函数定义中所描述的查找方式进行。

也就是说,从类范围开始搜索函数中使用的任何名称。

但是,函数本身在名称空间中是不可见的,除非它在类之外声明。

因此,在您的例子中,在类定义之前声明函数就足够了。

代码语言:javascript
复制
void f() {}

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

int main() {
    M m;
}

代码语言:javascript
复制
void f();

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

int main() {
    M m;
}
票数 3
EN

Stack Overflow用户

发布于 2014-05-08 12:01:59

关键问题是在什么情况下编译器能够/允许找到函数声明。对于一般的friend函数,您必须在类之外声明它,以便编译器能够找到它。

但是,有一个非常有用的例外:如果friend函数有一个类类型的参数,那么它能够找到函数,而不需要参数依赖的名称查找带来的额外声明。

这种情况实际上非常重要,因为通常您希望friend函数访问类类型的对象。

请考虑以下示例:

代码语言:javascript
复制
#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
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23540764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档