你应该能够在一个班级中定义一个朋友吗?

时间:2010-08-19 09:02:38

标签: c++

以下代码在gcc:

下编译正常
class vec3
{

private:

  float data[3];

public:

  vec3(float x, float y, float z)
  {
    data[0] = x;
    data[1] = y;
    data[2] = z;
  }

  void operator =(const vec3 &v)
  {
    data[0] = v.data[0];
    data[1] = v.data[1];
    data[2] = v.data[2];
  }

  friend vec3 operator *(float a, const vec3 &v)
  {
    vec3 res(v.data[0], v.data[1], v.data[2]);
    res.data[0] *= a;
    res.data[1] *= a;
    res.data[2] *= a;
    return res;
  }

};

int main(int argc, char **argv)
{
  vec3 v(1.0, 2.0, 3.0);
  vec3 u = 2*v;
  return 0;
 }

似乎操作符*是在类中定义的,它被编译为非成员函数,因为它被声明为朋友。这是标准行为吗?这似乎是一种定义非成员函数的奇怪方法,我没有看到这种在任何text-books / faqs中定义非成员朋友的方式(通常在类中声明并在外部定义)。

詹姆斯

3 个答案:

答案 0 :(得分:2)

这是标准且非常有用。即使不需要友谊(即只有流式公共值),我经常在一些类“X”中定义:

friend std::ostream& operator<<(std::ostream& os, const X& x)
{
    return os << x.a << " & " << x.b;
}

在您的示例中,operator *需要是访问数据的朋友,但需要是非成员,因为lhs值不是类的实例。不要被它所定义的事实所迷惑 - 在类中不同于仅被声明的事物。这不会改变任何东西,除了函数隐式地好像“内联”限定(这只是编译器提示并且不保证内联),避免了在多个包含期间使用单定义规则的问题。

答案 1 :(得分:1)

是..

根据标准文档,11.4 Friends - 6

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

示例:

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

请注意,函数名称是非限定的,它是一个全局函数,它具有相关命名空间的作用域。

答案 2 :(得分:0)

这是标准行为,我在Effective C ++中至少看过一次。