[英]How to overload operators with a built-in return type?
假設我有一堂課,其中包含一些數學運算。 讓我們用一個玩具的例子
class Test
{
public:
Test( float f ) : mFloat( f ), mIsInt( false ) {}
float mFloat;
int mInt;
bool mIsFloat;
};
我想使用以下原型創建運算符重載:
float operator=( const Test& test )
{
if ( !test.mIsFloat ) return *this; // in this case don't actually do the assignment
return test.mFloat; // in this case do it.
}
所以我的問題是:我可以使用內置的返回類型重載operator =嗎? 如果是的話,有沒有辦法引用內置類型?
我知道如果我用一個類包裝內置組件,我可以做到這一點。 但是在這種情況下,我想讓賦值運算符在LHS上使用內置類型
用法示例:
Test t( 0.5f );
float f = t; // f == 0.5
int i = 0;
i = t; // i stays 0.
更新:非常感謝您的幫助。 從玩具示例中擴展一點,使人們了解我真正想做的事情。
我有一個配置系統,允許我從具有不同類型的參數樹中獲取配置參數(它們可以是整數,浮點數,字符串,數組等)。
我可以通過以下操作從樹中獲取項目:
float updateTime = config["system.updateTime"];
但是可能“ system.updateTime”不存在。 或類型錯誤。 通常對於配置,我有一組默認值,然后編寫代碼以覆蓋config中的默認值:
float updateTime = 10;
const char* logFile = "tmp.log";
... etc etc...
我想做類似的事情:
updateTime = config["system.updateTime"];
如果存在覆蓋,則操作成功。 因此,如果operator []的返回是樹中的“無效”節點,則通常不會發生分配。
現在,我用類似的函數來解決它:
getConfig( config, "system.updateTime", updateTime );
但是我更喜歡使用賦值運算符。
如果我願意創建包裝內置函數的類,則可以這樣做。
class MyFloat
{
operator=( const Test& test ) { if (test.isValidNode() ) f = test.float(); return *this; }
float f;
}
但是顯然,最好不要用瑣碎的類包裝內置組件,而只是為了重載分配。 問題是-這可能在c ++中嗎?
根據您的示例,您真正想要的是一個隱式轉換運算符:
class Test
{
// ...
public:
operator float() const;
};
inline Test::operator float() const
{
return mIsFloat ? mFloat : mInt;
}
如果要有條件地進行分配,則需要采取另一種方法。 考慮到所有因素,命名方法可能是最好的選擇……
class Test
{
public:
bool try_assign(float & f) const;
};
inline bool Test::try_assign(float & f) const
{
if (mIsFloat) {
f = mFloat;
}
return mIsFloat;
}
無論執行什么操作,請注意,引入的語法糖不會導致無法閱讀的代碼。
您已經有一個從float
到Test
隱式轉換,形式為convert構造函數
class Test
{
public:
/* ... */
Test( float f ) : mFloat( f ) /*...*/ {}
};
它將支持以下轉換:
Test t(0.5f);
您可能還希望使用一個復制分配運算符,以實現從float
到Test
進一步隱式轉換:
class Test
{
public:
Test& operator=(float f) { mFloat = f; return *this; }
};
t = 0.75; // This is possible now
為了支持從Test
到float
隱式轉換,您不使用operator=
,而是這樣聲明並實現的自定義強制轉換運算符:
class Test
{
public:
/* ... */
operator float () const { return mFloat; }
};
這使得隱式轉換成為可能,例如:
float f = t;
順便說一句,您可能還不知道在這里發生了另一個隱式轉換。 在此代碼中:
Test t( 0.5 );
文字值0.5
不是float
,而是double
。 為了調用convert構造函數,必須將該值轉換為float
,這可能會導致精度損失。 為了指定float
文字,請使用f
后綴:
Test t( 0.5f );
使用模板專業化:
class Config {
template<typename T>
void setValue(const std::string& index, T& value); //sets the value if available
};
template<float>
void Config::setValue(const std::string& index, float& value){...} //only sets float values
template<int>
void Config::setValue(const std::string& index, int& value){...} //only sets int values;
您不能為基本類型“重載/添加”運算符,但可以為Type
。 但這不應該是operator =
而是operator >>
-像在istream
一樣。
class Test
{
public:
float mFloat;
int mInt;
bool mIsFloat;
Test& operator >> (float& v) { if (mIsFloat) v = mFloat; return *this; }
Test& operator >> (int& v) { if (!mIsFloat) v = mInt; return *this; }
};
那么你也能:
int main() {
float v = 2;
Test t = { 1.0, 2, false };
t >> v; // no effect
t.mIsFloat = true;
t >> v; // now v is changed
}
更新資料
我想做類似的事情:
updateTime = config["system.updateTime"];
然后根據我的建議,您可以:
config["system.updateTime"] >> updateTime;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.