你应该能够在课堂上定义一个朋友吗?

问题描述:

下面的代码下的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; 
} 

似乎寿操作*,是因为它被声明为朋友被编译为一个非成员函数的类中定义。这是标准行为吗?定义一个非成员函数似乎有些奇怪,我还没有看到在任何课本/常见问题(通常在课堂中声明并在外面定义)中定义非成员朋友的方式。

james

+0

是。我讨厌人们这样做。这很难告诉非会员。我更喜欢定义与课堂分开的朋友(也是我们编码标准的一部分)。但这是合法的。 – 2010-08-19 15:22:25

是..

根据标准文档,11.4 Friends - 6

的函数可以在一个类的一个朋友声明来定义当且仅当所述类是一个非局部类(9.8), 函数 名称不合格,函数具有命名空间范围

实施例:

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

注意,函数名是不合格的,它是一个全局函数,其具有在它被定义,其中相关联的命名空间的范围..

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

+0

好吧,那么我必须在那个例子上剔除。 – 2010-08-19 09:10:31

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

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

在你的榜样,操作*必须是一个好友才能访问数据,但需求成为非成员,因为lhs值不是该类的一个实例。不要被它在课堂上定义的事实所困惑 - 与仅仅声明 - 不同。这不会改变任何东西,除非该函数隐含地像“inline”限定的那样(这只是编译器提示并且不能保证内联),从而避免了在多重包含期间使用one-definition规则的问题。

+0

是的,它是非常有用的,我只是从外部定义的负载方法转移到里面...这使得代码读取更好,并节省了我的班级的声明负载:) – 2010-08-19 09:51:05

+0

@james edge:是那个讽刺? – 2010-08-19 15:24:03