[英]Operator overload in class templates and friendship
假設我有一個小班模板如下
template<typename T> class SillyClass {
public:
SillyClass(const T val);
SillyClass(const SillyClass& other);
private:
T data;
};
現在我添加以下
定義
聲明:
template<typename T> class SillyClass {
public:
SillyClass(const T val);
SillyClass(const SillyClass& other);
SillyClass<T> operator+ (const SillyClass& other);
SillyClass<T> operator+ (const T& val);
private:
T data;
};
現在(在我寫下適當的定義之后)我可以做這樣的事情
SillyClass<int> a(1);
SillyClass<int> b(a);
SillyClass<int> c = a + b;
SillyClass<int> d = a + 3;
到現在為止還挺好。 但是,為了能夠寫出類似的東西
SillyClass<int> e = 3 + a;
我發現必須在我的類中添加以下聲明
template<typename T2> friend SillyClass<T2> operator+
(const T2& val, const SillyClass<T2>& other);
所以它現在讀
template<typename T> class SillyClass {
public:
SillyClass(const T val);
SillyClass(const SillyClass& other);
SillyClass<T> operator+ (const SillyClass& other);
SillyClass<T> operator+ (const T& val);
template<typename TT> SillyClass<TT> friend operator+
(const TT& val, const SillyClass<TT>& other);
private:
T data;
};
我沒有在一本書中找到這個,我需要一些幫助來理解最后一個聲明中發生的事情。 例如,我的班級在這里結交的是什么? 為什么要額外的模板聲明? 對於導致相同結果的不同聲明(例如,能夠執行 3+a),我有哪些替代方案?
謝謝。
您不僅可以在類中聲明運算符,還可以在類中定義friend
運算符:
SillyClass<T> friend operator+(const T& val, const SillyClass<T>& other)
{
// define it here
}
這樣,對於您的類的每個實例,都會生成一個相應的friend
。 整個過程基於一個叫做朋友名字注入的東西。
現在回到你的問題。 如果您只是使用類內聲明
friend operator+(const T& val, const SillyClass<T>& other);
然后在你的課外你定義
template<typename T>
friend operator+(const T& val, const SillyClass<T>& other)
你會得到一個鏈接器錯誤。 為什么? 因為在實例化類時假設T=int
。 然后你班級中的聲明將讀作
friend operator+(const int& val, const SillyClass<int>& other);
並且每當您在SillyClass<int>
和一些int
上調用您的operator+
時,都會比上面的模板定義更好的匹配。 因此鏈接器將無法找到所需int
實例化的定義,因此會出現鏈接器錯誤。 另一方面,我在答案開頭提出的解決方案保證了每種類型都有相應的定義,因此它可以毫無問題地工作。
我的班級在這里交朋友是為了什么? 為什么要額外的模板聲明?
在您的類中聲明的以下表達式是友元聲明:
template<typename TT> SillyClass<TT> friend operator+
(const TT& val, const SillyClass<TT>& other);
上面的表達式將您的類聲明為具有一系列重載operator+
的朋友,這些operator+
將類型TT
作為其左側參數,並將對象SillyClass<TT>
作為其右側。 請注意,這是一個聲明而不是定義。 也就是說,為了使其工作,必須定義模板重載operator+
。
對於導致相同結果的不同聲明(例如,能夠執行 3+a),我有哪些替代方案?
對於二元運算符,為了使它們對稱,必須在類定義之外將其聲明為自由函數,並且為了能夠訪問其類參數的私有成員,您將它們聲明為相應類的友元函數。
基於這些行,我將采用以下實現:
template<typename T> class SillyClass {
T data;
public:
SillyClass(const T val) : data(val) {}
SillyClass(const SillyClass& other) : data(other.data) {}
template<typename T1, typename T2>
friend SillyClass<typename std::common_type<T1, T2>::type>
operator+(SillyClass<T1> const &lsh, SillyClass<T2>& rhs);
template<typename T1, typename T2>
friend SillyClass<typename std::common_type<T1, T2>::type>
operator+(SillyClass<T1> const &lsh, T2 const &rhs);
template<typename T1, typename T2>
friend SillyClass<typename std::common_type<T1, T2>::type>
operator+(T1 const &rhs, SillyClass<T2> const &rsh);
};
template<typename T1, typename T2>
SillyClass<typename std::common_type<T1, T2>::type>
operator+(SillyClass<T1> const &lhs, SillyClass<T2>& rhs) {
return SillyClass<typename std::common_type<T1, T2>::type>(lhs.data + rhs.data);
}
template<typename T1, typename T2>
SillyClass<typename std::common_type<T1, T2>::type>
operator+(SillyClass<T1> const &lhs, T2 const &rhs) {
return SillyClass<typename std::common_type<T1, T2>::type>(lhs.data + rhs);
}
template<typename T1, typename T2>
SillyClass<typename std::common_type<T1, T2>::type>
operator+(T1 const &lhs, SillyClass<T2> const &rhs) {
return SillyClass<typename std::common_type<T1, T2>::type>(rhs.data + lhs);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.