簡體   English   中英

如何使用內置返回類型重載運算符?

[英]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;
}

無論執行什么操作,請注意,引入的語法糖不會導致無法閱讀的代碼。

您已經有一個從floatTest隱式轉換,形式為convert構造函數

class Test
{
public:
 /* ... */
Test( float f ) : mFloat( f ) /*...*/ {}       

};

它將支持以下轉換:

Test t(0.5f);

您可能還希望使用一個復制分配運算符,以實現從floatTest進一步隱式轉換:

class Test
{
public:

    Test& operator=(float f) { mFloat = f; return *this; }  
};

t = 0.75; // This is possible now

為了支持從Testfloat隱式轉換,您不使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM