在實作專案時,結合 namespace 與 friend 函數常導致令人困惑的編譯錯誤。本文透過實際代碼示範,深入剖析兩大核心問題的成因與標準解法,助你避開常見陷阱。
namespace N 內,friend void f(); 預設指向 N::f。:::可強制指向全域命名空間的函數。namespace elephant {
class CA {
int a;
friend istream& operator>>(istream&, CA&); // 未聲明
};
}
// 定義在全域空間
istream& operator>>(istream& is, elephant::CA& a) {
is >> a.a; // error: 'int elephant::CA::a' is private
return is;
}
錯誤原因:類別內的 friend 宣告預設尋找 elephant::operator>>,但實際定義在全域空間,導致授權失效。
namespace elephant {
class CA {
int a;
friend istream& operator>>(istream&, CA&);
};
// 關鍵:在 namespace 內聲明
istream& operator>>(istream&, CA&);
}
// 定義時加上命名空間限定
istream& elephant::operator>>(istream& is, elephant::CA& a) {
is >> a.a; // OK
return is;
}
void output(int a);
namespace elephant { class SA; } // 前向聲明
void output(const elephant::SA&);
namespace elephant {
class SA {
int data;
friend void output(const SA&); // 指向 elephant::output
};
}
void output(const elephant::SA& a) { // 全域定義
output(a.data); // error: 無法存取私有成員
}
失敗原因:friend void output(const SA&) 在 elephant 內部,綁定 elephant::output,而非全域 ::output。
void output(int a);
namespace elephant { class SA; }
void output(const elephant::SA&);
namespace elephant {
class SA {
int data;
// 關鍵:明確指向全域空間
friend void ::output(const SA&);
};
}
void output(const elephant::SA& a) {
output(a.data); // OK
}
friend 不進行聲明,必須額外在對應作用域聲明函數原型。N::。elephant::f 與 ::f 是兩個不同函數,授權不互通。friend void ::func(...);。本文整理自「elephant_liu」博客,原文出處:https://elephantliu.blog.51cto.com/1107116/610844 | 測試環境:Ubuntu 10.10, g++ 4.4.5