看看下面的例子:有沒有辦法避免模板朋友聲明的外部可視性?
啊:
class A {
protected:
template<class T>
friend void b();
};
BH:
template<class T>
void b() {}
main.cxx:
#include "a.h"
int main()
{
b<double>();
}
請注意,我忘了,包括「 bh「在主文件中。不幸的是,編譯器會在A類中選擇好友聲明,並且無需抱怨地編譯主函數。我留下了一個神祕的鏈接錯誤,因爲實例應該發生在main.cxx這是令人驚訝:
[[email protected] friend]$ g++ main.cxx
/tmp/ccfpaeHw.o: In function `main':
main.cxx:(.text+0x5): undefined reference to `void b<double>()'
collect2: error: ld returned 1 exit status
我的問題是:爲什麼編譯器還允許嗎?有沒有辦法呢?
通過單獨編譯的原則,每個翻譯單元 (TU)是分開編譯的,只要TU所需的所有信息在編譯時可用即可。對於帶有b簽名的函數,它當然是(在預編譯器將a.h移入main.cpp之後)。未解析的引用被輸入到符號表中,由鏈接器解析(因此鏈接器錯誤)。我不知道如何(或爲什麼)來避免這種情況。 – gnometorule
爲什麼要避免這種情況?因爲它很醜!提及作爲一個班級的朋友存在的功能不應該允許外部代碼使用它,恕我直言。我確信這種行爲有很好的技術原因,但是找到一種方法可以讓外部代碼無法使用這個聲明,這樣可以避免錯誤,特別是對於初學者。 –
'爲什麼'更像是一個技術問題。如果你經歷了編譯器/鏈接器採取的步驟,這將很難實現(例如,你需要一些跨TU有效性檢查)。 C(++)傳統上使用「單獨編譯」,這是不可能的。是的,我同意,這可能導致在調試時難以跟蹤錯誤。 – gnometorule