在這段代碼中,為什么不能在運算子多載中訪問我的類的私有欄位?
(請注意,這只是一個 MRE,不是完整代碼)
template <typename T>
class Frac
template <typename T, typename U>
Frac<T> operator (Frac<T> lhs,const Frac<U>& rhs);
template <typename T, typename U>
bool operator==(const Frac<T>& lhs, const Frac<U>& rhs);
template <typename T>
class Frac {
template<typename>
friend class Frac;
friend Frac operator <>(Frac lhs,const Frac& rhs);
friend bool operator== <>(const Frac& lhs, const Frac& rhs);
private:
T numerator, denominator;
};
template <typename T, typename U>
Frac<T> operator (Frac<T> lhs,const Frac<U>& rhs) {
lhs.denominator = rhs.denominator;
return lhs;
}
template <typename T, typename U>
bool operator==(const Frac<T>& lhs, const Frac<U>& rhs) {
return (lhs.numerator == rhs.numerator && lhs.denominator == rhs.denominator);
}
當我編譯時,編譯器告訴我不能訪問分母和分子欄位,因為它們是私有的。但是,過載被指示為友好。該類也被指示為友好的,因此無論型別如何,該類的所有實體都是友好的。
有人可以解釋一下問題是什么以及如何解決嗎?
uj5u.com熱心網友回復:
無法訪問分母和分子欄位,因為它們是私有的。
是的,您還沒有制作免費功能friend。您已經制作了 classes friend,但這對免費功能沒有幫助。一種更簡單的解決方案是在類定義中定義它們。
例子:
template <typename U>
friend Frac operator (Frac lhs, const Frac<U>& rhs) {
lhs.denominator = rhs.denominator;
return lhs;
}
但是,如果您改為創建成員函式,則operator 可以將其實作為沒有任何friend船舶的自由operator =函式。friend所有Frac<>s之間的船已經建立,因此不需要額外的friend宣告。
例子:
#include <iostream>
#include <utility>
template <typename T>
class Frac {
public:
template <typename> // be friends with all Frac's
friend class Frac;
Frac() = default; // needed because for the templated converting ctor below
// a converting constructor from any Frac:
template<class U>
explicit Frac(const Frac<U>& rhs) :
numerator(rhs.numerator), denominator(rhs.denominator) {}
template <typename U>
Frac& operator =(const Frac<U>& rhs) {
denominator = rhs.denominator; // ok: rhs has befriended Frac<T>
return *this;
}
template <typename U>
bool operator==(const Frac<U>& rhs) const {
// ok: rhs has befriended Frac<T> here too
return numerator == rhs.numerator && denominator == rhs.denominator;
}
private:
T numerator{}, denominator{};
};
// This free function doesn't need to be a friend. It uses the member function
// operator =
// The returned type, Fact<R>, is deduced by fetching the type you'd gotten
// if you add a T and U.
template<typename T, typename U,
typename R = decltype(std::declval<T>() std::declval<U>())>
Frac<R> operator (const Frac<T>& lhs, const Frac<U>& rhs) {
Frac<R> rv(lhs); // use the converting constructor
rv = rhs;
return rv;
}
int main() {
Frac<int> foo;
Frac<double> bar;
auto r = foo bar; // r is a Frac<double> (int double => double)
}
uj5u.com熱心網友回復:
使每個實體
template <typename T, typename U>
bool operator==(const Frac<T>& lhs, const Frac<U>& rhs);
朋友,你需要在你的friend宣告中同樣冗長。復制此宣告并friend在其中粘貼“ ”。有兩個怪癖。首先,template必須在之前friend,因此您將在宣告中間添加關鍵字。其次,T它已經被用作類的模板引數,因此您應該選擇不同的識別符號以避免陰影(我將使用S)。
template <typename S, typename U>
// ^^^
friend bool operator==(const Frac<S>& lhs, const Frac<U>& rhs);
// ^^^^^^ ^^^
如果沒有這個改變,你說的朋友Frac<T>是一個接受兩個Frac<T>引數(相同T)的運算子。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/406382.html
標籤:
