我試圖讓乘法運算符成爲名爲TVector3的模板類的朋友。我已經讀過,我可以在聲明它在類聲明中之前先聲明好友函數,但是我嘗試這麼做是徒勞的。我知道我可以簡單地定義朋友函數而不是聲明它,但我希望它能夠使用前向聲明技術。模板類中的朋友函數
特別是我試圖爲我的情況實施this解決方案。我發現this的帖子也是David Rodriguez提供的解決方案(第三版),但我不知道我做錯了什麼。
予編譯使用 '克++ template.cpp tempmain.cpp一個' 和編譯器(克++)提供了以下錯誤:
未定義參照「射線:: TVector3射線::運算符*(浮,射線:: TVector3常量&)」
爲以下代碼:
template.h:
#ifndef TVECTOR_H
#define TVECTOR_H
#include <cmath>
namespace ray
{
//forward declarations
template <class T> class TVector3;
template <class T> TVector3<T> operator* (T, const TVector3<T> &);
template <class T>
class TVector3 {
public:
union {
struct {
T x, y, z;
};
T xyz[3];
};
//function needed
friend TVector3<T> operator*<T> (T, const TVector3<T> &);
};
}
#endif
template.cpp:
#include "template.h"
using namespace ray;
//friend operator function
template<class T> TVector3<T> operator * (T f, const TVector3<T> &v)
{
return TVector3<T>(f * v.x, f * v.y, f * v.z);
}
//instantiate template of type float
template class TVector3<float>;
tempmain.cpp:
#include <iostream>
#include "template.h"
int main()
{
ray::TVector3<float> v1, v2;
v2.x = 3;
v1 = 4.0f * v2; //this reports as undefined
std::cout << v1.x << "\n";
return 0;
}
即完整源代碼。我究竟做錯了什麼?
在我的情況,我會如何實例化操作*模板?我假設我需要在cpp文件中做到這一點。我正在試圖這樣做,作爲一個練習。另外我還有一個問題,當頭文件被包含在其他cpp源文件中時,不會在頭文件中定義模板類,從而臃腫可執行文件? 感謝您的建議BTW和您的及時回覆:) – Kevin
@Kevin:實例化模板的代碼是在答案,第一行。請注意,這是一個很少使用的功能,因此它可能無法編譯(如果是這樣,請告訴我),但它應該是正確的。關於代碼膨脹,模板的顯式實例更容易出現代碼膨脹。當你明確地實例化一個模板時,所有的成員函數都被實例化(以及在類模板中定義的朋友)。另一方面,通過隱式實例化(頭文件中的所有模板定義),編譯器將按需生成函數,因此可執行文件將包含更少的代碼。 –
@Kevin:...雖然,因爲定義在標題中,所以多個翻譯單元*使用*(* odr-use *)相同的成員函數,編譯器將在所有翻譯單元中生成代碼,鏈接器放棄除一個定義之外的所有內容。但是在鏈接器完成後,只有每個使用函數的一個副本將在可執行文件中。同時,編譯時間可能會更長(相同的代碼將被多次生成,以後纔會被丟棄)。但這個問題很少。 –