2010-10-28 80 views
0

我有一些錯誤代碼的代碼我不明白如何解決。我問過我的教授和助教,除了更準確地理解錯誤的含義外,沒有運氣就諮詢了互聯網。從我所知道的來看,編譯器會讓我的重載操作符與內置操作符混淆,或者它根本不認爲它是一個重載操作符。關於C++模板上的重載操作符的一些編譯錯誤

我收到以下錯誤和警告:

|| ===項目4項,調試=== | \ project 4 \ forest.h | 13 | warning:friend declaration'Forest & operator +(Forest &,Forest &)'聲明瞭非模板函數|注意:(如果這不是你想要的,請確保函數模板已經被聲明,並且在函數名稱後面加上<>)|

\ project 4 \ forest.h | 13 |

\項目4 \ forest.h | 14 |警告:朋友宣言 '的std :: ostream的&操作< <(STD :: ostream的&,常量森林&)' 聲明一個非模板函數|

\項目4 \ forest.h | 15 |警告:朋友宣言 '的std :: istream的&操作>>(的std :: istream的&,森林&)' 聲明一個非模板函數|

\ project 4 \ main.cpp ||在函數'int main()'中: \ project 4 \ main.cpp | 21 | error:'文件>> intForest'中'操作符'的模糊重載|

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 119 |注意:考生是:std :: basic_istream < _CharT ,_Traits> &的std :: basic_istream < _CharT,_Traits> ::運算>>(標準:: basic_istream < _CharT,_Traits> &(*)(標準:: basic_istream < _CharT,_Traits> &))[用_CharT =炭,_Traits = std :: char_traits] |

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 123 | note:std :: basic_istream < _CharT,_Traits> &的std :: basic_istream < _CharT,_Traits> ::運算>>(標準:: basic_ios < _CharT,_Traits> &(*)(標準:: basic_ios < _CharT,_Traits> &))[用_CharT =炭,_Traits = std :: char_traits] |

c:\ program files(x86)\ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 130 | note:std :: basic_istream < _CharT,_Traits> & std :: basic_istream < _CharT,_Traits> :: operator >>(std :: ios_base &(*)(std :: ios_base &))[with _CharT = char,_Traits = std :: char_traits] | || ===構建完成:1個錯誤,3個警告=== |

當我嘗試編譯我的代碼。相關的代碼段如下:

(在forest.h)

template< typename NODETYPE > class Forest 
{ 

    public: 
     friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&); 
     friend ostream& operator<<(ostream&, const Forest<NODETYPE>&); 
     friend istream& operator>>(istream&, Forest<NODETYPE>&); 

     Forest(); 
     Forest(const Forest& otherForest); 
     ~Forest(); 
     void nodes(int&) const; 

    private: 
     ForestNode<NODETYPE> *root; 

     ForestNode<NODETYPE> *getNewNode(const NODETYPE &); 
}; 

(在森林

。CPP)

template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1) 
{ 
    istream file2 = file; 
    int nodeCount = 0; 
    string blah = ' '; 

    while(getline(file2,blah)) 
    { 
     nodeCount++; 
    } 

    ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i 

    getline(file,*f1.root.tag); 
    forestNodeArray[0] = &(*f1.root); 
    inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount); 

    return file; 
} 

(終於,在main.cpp中)

int main() 
{ 

    Forest <char> intForest(); 
    filebuf fb; 
    fb.open ("forest1.txt",ios::in); 
    istream file(&fb); 


    cout << typeid(intForest).name() << endl; 
    cout << typeid(file).name() << endl; 

    file >> intForest; 

    fb.close(); 


} 

任何幫助將不勝感激。

編輯:感謝亞歷克斯和阿爾夫,我明白他們爲什麼不被視爲模板功能。回想起來很明顯,我只是設置了這些簽名。無論如何,我仍然得到關於模糊運算符的錯誤。爲什麼編譯器不能識別我的操作符並使用它,而不是試圖在操作符的3個內置版本之間做出決定,這些操作符不可能有一個參數爲Forest?

+0

嘗試'模板<>朋友森林與運營商+' – 2010-10-28 05:28:13

+0

@alex啊。這解決了警告。謝謝。我有點希望聲明保持原來的樣子,這是由於我的教授給出的項目指南中指定的函數簽名,但我開始越來越關注遵守這些函數簽名和更多關於有工作代碼。再次感謝。 – joedillian 2010-10-28 05:36:28

+0

好吧,如果你仔細想想,朋友函數的簽名取決於你的模板參數'NODETYPE',所以它們也必須是模板。沒有辦法繞過它。 – 2010-10-28 16:32:29

回答

1

第二個錯誤是在這條線:

Forest <char> intForest(); 

這可能是起初令人驚訝,但該行並未聲明Forest<char>類型的變量,而是一個不帶參數並返回的函數。 剛剛從聲明中刪除括號:

Forest <char> intForest; 

在第一次警告,這已經是解釋(聲明爲友元函數不是一個模板,這意味着你將必須手動實現它爲每種類型你可以用Forest<>來實例化(可能你不想這麼做)。還要注意聲明模板operator+,然後把模板變成朋友,就像@Alf P. Steinbach的回答意味着Forest<int>將會是Forest<double>的朋友,這可能不是你所需要的。@Alex提議在評論中只會將模板的特定實例化成一個朋友,這可能更接近你想要的,但是你需要聲明模板操作模板類之前,以及您需要轉發聲明模板類...

在模板朋友免費功能的一個常見的模式是定義函數的地方:

template <typename T> 
class Forest { 
    // ... 
    friend Forest& operator+(Forest const & lhs, Forest const & rhs) [1] 
    { 
     // implementation here 
    } 
} 
// [1] Note that the arguments are const references (read only), and also note that 
//  you do not need to provide the type argument inside the template declaration 

這允許您將其定義爲非模板化函數,同時讓編譯器爲您實例化該函數。此外,在處理模板時定義類定義中內聯的成員方法通常也更簡單。它使生活變得更簡單,畢竟在大多數情況下,您確實需要在(相同的)頭文件中提供實現。

但是,在定義二元運算符時,更好的方法是將operator+=定義爲成員方法,然後可以很容易將operator+定義爲非友元函數。該模式將是:

struct test { 
    test& operator+=(test const &); 
}; 
test operator+(test lhs, test const & rhs) { // [2] 
    lhs += rhs; 
    return lhs; 
} 
// [2] Note that the first argument is by value, and the second by const reference 
//  This means that the compiler will copy the first argument for you, and you 
//  are free to modify it with the += operator and return the copy. 

現在,最棘手的部分是混合前兩個建議。爲了能夠定義operator+該模板定義範圍內的免費功能,常用的伎倆是讓朋友即使不需要訪問的原因:

template <typename T> 
class Forest { 
    Forest& operator+=(Forest const &) { 
     // implemenation 
    } 
    friend Forest operator+(Forest lhs, Forest const & rhs) { // [3] 
     return lhs+=rhs; 
    } 
}; 
// [3] friendship only to allow us to define the free function inside the template 
//  declaration. 
+0

是的,我認爲這很奇怪。我的班級助教添加了那些()我已經按照你的建議。現在你說出它的實際含義了,這非常明顯。無論哪種方式,我仍然有一系列的錯誤,基本上說它不能識別我的超載>>操作符。下面是一個示例: \ project 4 \ main.cpp | 21 |錯誤:'文件>> intForest'中的'operator >>'不匹配。 c:\ program files(x86)\ codeblocks \ mingw \ bin \ .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ C++ \ istream | 119 |注意:應該是:std :: basic_istream <_CharT ,_Traits>&std :: basic_istream <_CharT,_Traits> :: operator >> ... – joedillian 2010-10-28 08:02:45

+0

然後繼續列出basic_istream類中的>>運算符的每個實例。 – joedillian 2010-10-28 08:06:48

+0

我無法在編譯器列出的三個候選人中找到我的頭。 – Chubsdad 2010-10-28 08:13:03

0

(第一次)警告告訴你友好函數不是模板。

而事實並非如此。

想想你將如何實現它。這需要爲每個可能的NODE_TYPE編寫一個這樣的函數。

有幾種方法可以解決這個問題。

的一種方法是去親近一個函數模板,如下所示:。

template< class Type > 
struct S 
{ 
    template< class U > friend void foo(S<U>); 
}; 

template< class Type > 
void foo(S<Type> x) {} 

int main() 
{} 

乾杯& HTH,

+0

謝謝alf。你和alex明確說明了做這些事情的正確語法,我的Dietel參考資料沒有任何通用朋友函數的例子。如果你可能想知道爲什麼C++會把我的>>操作符和內建在istream中的操作符混淆起來,那會很好,但是感謝你給的幫助。 – joedillian 2010-10-28 05:48:02

0

學習C++,我也遇到了同樣的問題但我以另一種方式解決了它!

template <class NODETYPE> class Forest; 
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&); 
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&); 
template <class NODETYPE> istream& operator>> (istream&, Forest<NODETYPE>&); 
template<class NODETYPE> 
template< typename NODETYPE > 
class Forest 
{ 

    public: 
     friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&); 
     friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&); 
     friend istream& operator>> <>(istream&, Forest<NODETYPE>&); 

     Forest(); 
     Forest(const Forest& otherForest); 
     ~Forest(); 
     void nodes(int&) const; 

    private: 
     ForestNode<NODETYPE> *root; 

     ForestNode<NODETYPE> *getNewNode(const NODETYPE &); 
};