g ++ 4.5找不到好友功能

时间:2011-03-22 13:20:35

标签: c++ g++ friend

天儿真好!

我对在C ++中使用friend有疑问。请考虑以下代码:

#include <ostream>

struct F {
};

struct N {
  friend std::ostream& operator<< (std::ostream&, const N&);
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

void foo(std::ostream &out) {
  F bar;
  out << bar;
}

我的理解始终是,friendstatic类似,具有friend函数可以访问类的私有部分的附加属性。在这个假设下,代码应该编译,因为operator<<有一个ostream&和一个(const)F&

g ++ 4.0似乎与我分享了我的想法,因为它接受了这个代码。然而,更新的g ++ 4.5(.2)拒绝带有消息的代码:

ns.cc: In function 'void foo(std::ostream&)':
ns.cc:14:10: error: no match for 'operator<<' in 'out << bar'

是g ++ 4.5错了还是我(和g ++ 4.0)错了?

(将好友声明移到F课程的解决方案没有帮助,因为operator<<需要访问N的私有部分。)

此致 斯蒂芬

3 个答案:

答案 0 :(得分:5)

问题是,除非您提供内联实现,否则友元声明不会提供全局函数声明。

struct N {
   friend void func1() { }
   friend void func2();
   friend void func3();
};

void func3();

func1(); /* OK */
func2(); /* not OK */
func3(); /* OK */

答案 1 :(得分:4)

您还必须在结构外部声明运算符。 gcc 4.4报告了相同的错误。

#include <ostream>

struct F {
};

struct N {
  friend std::ostream& operator<< (std::ostream&, const N&);
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

std::ostream& operator<< (std::ostream&, const N&);
std::ostream& operator<< (std::ostream&, const F&);    

void foo(std::ostream &out) {
  F bar;
  out << bar;
}

答案 2 :(得分:0)

自从我看到问题以来,我一直在跋涉标准(FCD,n3242)

[class.friend] 中可以阅读:

  

6)当且仅当该类是非本地类(9.8),函数名称不合格且函数具有命名空间范围时,才能在类的友元声明中定义函数。

     

7)这样的功能是隐式内联的。在类中定义的友元函数位于定义它的类的(词法)范围内。在课外定义的朋友函数不是(3.4.1)。

     

9)朋友声明提名的名称应在包含朋友声明的类的范围内访问。

那么,这里会发生什么?

struct F {
};

struct N {
  friend std::ostream& operator<< (std::ostream&, const F&);    
};

朋友声明提名operator<<的这个重载是N的朋友。但是,这个重载尚未在词法范围(命名空间或类)中声明。另外,7不适用,因为它未在N内定义。

因此,在查找可应用于operator<<的重载时:

void foo(std::ostream &out) {
  F bar;
  out << bar;
}

没有有效的过载(实际上,可能根本没有过载)。

您有两种解决方案:

  • 使用7:在朋友声明之后定义内联函数。
  • 使用9:声明命名空间中的函数

因为4

  

4)在朋友声明中首先声明的函数具有外部链接(3.5)。否则,该函数将保留其先前的链接(7.1.1)。

我建议将之前声明为friend声明来控制其链接,但这很少有用。