2010-06-03 70 views
4

我試圖使用朋友函數來重載< <和模板以熟悉模板。我不知道這些編譯錯誤是:朋友,模板,重載<<

Point.cpp:11: error: shadows template parm 'class T' 
Point.cpp:12: error: declaration of 'const Point<T>& T' 

此文件

#include "Point.h" 

template <class T> 
Point<T>::Point() : xCoordinate(0), yCoordinate(0) 
{} 

template <class T> 
Point<T>::Point(T xCoordinate, T yCoordinate) : xCoordinate(xCoordinate), yCoordinate(yCoordinate) 
{} 

template <class T> 
std::ostream &operator<<(std::ostream &out, const Point<T> &T) 
{ 
    std::cout << "(" << T.xCoordinate << ", " << T.yCoordinate << ")"; 
    return out; 
} 

我的頭看起來像:

#ifndef POINT_H 
#define POINT_H 

#include <iostream> 

template <class T> 
class Point 
{ 
public: 
    Point(); 
    Point(T xCoordinate, T yCoordinate); 
    friend std::ostream &operator<<(std::ostream &out, const Point<T> &T); 

private: 
    T xCoordinate; 
    T yCoordinate; 
}; 

#endif 

我的頭也給出了警告:

Point.h:12: warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Point<T>&)' declares a non-template function 

我還不確定爲什麼。有什麼想法嗎?謝謝。

+0

你在用什麼編譯器?該代碼甚至適用於VC6 – YeenFei 2010-06-03 07:03:07

+0

@YeenFei:一切工作在VC6! – 2010-06-03 07:05:50

+0

XCode IDE。那是GNU編譯器嗎? – Crystal 2010-06-03 07:14:59

回答

3

模板參數和函數參數都具有相同的名稱。將其更改爲類似:

template <class T> 
std::ostream &operator<<(std::ostream &out, const Point<T> &point) 
{ 
    std::cout << "(" << point.xCoordinate << ", " << point.yCoordinate << ")"; 
    return out; 
} 

頭中的友元函數的聲明也應該被改變:

template <class G> 
friend std::ostream &operator<<(std::ostream &out, const Point<G> &point); 
+0

模板對於標題和實現文件的評論必須不同嗎?或者他們都可以成爲T級的? – Crystal 2010-06-03 07:12:54

+0

問題是在頭文件中嵌套的會給你一個類似的陰影錯誤。如果您將它們都設爲G或U或任何您喜歡的類型,則可以在兩個文件中使用相同的類型參數名稱。 – 2010-06-03 08:57:55

1

@Firas已經回答了你的第一個問題,所以我不會重複這裏。

關於第二個問題,它警告你一下:

friend std::ostream &operator<<(std::ostream &out, const Point<T> &T); 

該聲明是一個類模板:

template <class T> 
class Point { // ... 

它告訴你,即使你可以在許多不同的實例Point類型,你是說 - 模板operator<<是他們所有人的朋友。即,即使存在潛在的無限種不同種類的Points,你說他們只有一個operator<<

事實上,這似乎是在你的代碼錯誤 - 你定義operator<<作爲一個函數模板,但宣佈(非模板)功能類的朋友(一說你的代碼似乎沒有定義)。 IOW,這樣的定義:

template <class T> 
std::ostream &operator<<(std::ostream &out, const Point<T> &T) 

...是一個模板,這是爲你指出,在朋友聲明之上(雖然我認爲你打算它們匹配)同樣的事情。

0

這裏有一個細微的錯誤(不相關):模板方法的定義最好放在標題中,因爲它們應該(通常)對調用者可見。

針對您的編譯問題:正如警告所述,您正試圖聲明非模板好友功能。如果你糾正它,那麼問題會神奇地得到解決。

template <class T> 
class Point 
{ 
public: 
    template <class U> 
    friend std::ostream& operator<<(std::ostream& out, const Point<T>& p); 
}; 

但真正的問題是你需要一個friend聲明在這裏?公衆是否可以訪問xy座標(至少在只讀模式下)?

// Free functions 
template <class T> 
std::ostream& operator<<(std::ostream& out, const Point<T>& p) 
{ 
    return out << '(' << p.x() << ", " << p.y() << ')'; 
} 

最後,請注意,這將是最好的,如果你的論點從範圍類型,並特別聲明你使用template語法的類型有不同的名稱。