2010-08-19 91 views
1

下面的代碼下的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

回答

1

是..

根據標準文檔,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 
}; 

注意,函數名是不合格的,它是一個全局函數,其具有在它被定義,其中相關聯的命名空間的範圍..

0

這是標準行爲,我在Effective C++中至少見過一次。

+0

好吧,那麼我必須在那個例子上剔除。 – 2010-08-19 09:10:31

2

這是標準的,非常有用。即使不需要友誼(即只流公共價值),我經常定義裏面的一些類「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

相關問題