通過聲明操作的朋友,你告訴編譯器查找功能
ostream& operator<<(ostream &,T);
其中T
是完全相同的類型B樹類模板進行實例化。 (例如:btree<Node>
,實際簽名會ostream& operator<<(ostream &, Node);
- 假設你HACE成員i
和Node
型n
)
此功能將可以訪問類btree<T>
的private和protected成員(變量和函數)的所有實例T
,但它實際上並不是該類的成員(因爲它不包含friend
關鍵字)。
操作定義您提供的是一個操作符是模板類B樹中的一員,因爲如果你有宣佈
template<class T>
class btree
{
public:
ostream& operator<<(ostream &,T);
};
這是由於包含的是btree<T>::
前綴(即指定功能/操作員屬於哪個類)。
由於該類中沒有相應的運算符聲明(請參閱上述對朋友聲明的描述),因此編譯器會抱怨。
要解決它,你要麼
- 保持朋友聲明,刪除操作確定指標的
btree<T>::
前綴和template<class T>
並更改第二個參數類型btree<Type>&
,其中Type
是的一個你期望btree模板被實例化的類型(例如Node
) - 然後爲其他類型提供類似的定義。
- 或移除聲明的
friend
關鍵字在類和從兩個聲明和定義如現在操作者應該對整個B樹工作(可經由隱式地提供除去T
參數*this
)。
- 或者,你可以聲明朋友經營者作爲模板進行實驗,但需要更多的修改:(閱讀更多關於forward declaration)
template<class T> btree; // forward declaration of class btree
// forward declare operator (or move definition here)
template<class T>
ostream& operator<<(ostream &o, btree<T>& s);
// declare operator as template friend
template<class T>
class btree
{
public:
friend ostream& operator<< <> (ostream &, bree<T>&);
// note <> after operator name to denote template with no new template parameters
};
注意,上面我認爲你想輸出整棵樹(即在btree對象上調用operator<<
)。從代碼中不清楚這是否是你的意圖(class btree沒有成員i
和n
)。 如果不是,並且您想要調用運算符的類型是btree的實際模板參數,則不需要從T
更改模板運算符的第二個參數,但是也不需要聲明它作爲類btree的friend
作爲運算符獨立於btree。如果i
和/或n
在該類別中是私密的,則您確實需要將其聲明爲類別的朋友,該類別的成員i
和n
您正在訪問定義者(例如上面的節點)。關於丟失btree<T>::
(或Node::
)的概念仍然適用,因爲運營商不屬於任何類別。
夫婦更多的事情,假設你去與朋友聲明:
- 到操作的類型,第二個參數應該是
btree<T>&
(強調&
),因爲它是更有效地傳遞reference到btree對象比複製整個btree(或使用指針的淺拷貝並使用缺省copy-contructor)
- 第二個參數也應該標記爲
const
,因爲(可能)您不希望在更改btree對象期間輸出。請注意,在這種情況下,您需要將btree<T>
中的某些不變方法標記爲const
以允許它進行編譯。 (參見const correctness的FAQ)
EDIT'd幾次說清楚,並確保正確性
http://sscce.org/(尤其是** **簡單)。 – Griwes 2012-03-26 15:47:08
該代碼看起來很冗長,但問題出現在類btree以及緊隨該類之後的重載<<運算符函數中。 – user1232138 2012-03-26 15:57:47
@OP,每當我看到如此高的滾動條時,就表示錯誤的測試用例。刪除必要的內容,然後它將是「簡單,自包含的正確示例」。 – Griwes 2012-03-26 16:05:50