1

假设我有一堂课,其中包含一些数学运算。让我们用一个玩具例子

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”可能不存在。或者是错误的类型。通常对于配置,我有一个默认值块,然后代码覆盖配置中的默认值:

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++ 中可能吗?

4

4 回答 4

3

根据您的示例,您真正想要的是一个隐式转换运算符:

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;
}

无论你做什么,都要小心你引入的语法糖不会导致不可读的代码。

于 2012-10-30T17:45:46.287 回答
1

您已经有一个从floatto的隐式转换,Test以 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不是 a float,而是 a double。为了调用 convert 构造函数,这个值必须被转换为float,这可能会导致精度损失。要指定float文字,请使用f后缀:

Test t( 0.5f );
于 2012-10-30T17:51:19.803 回答
1

使用模板特化:

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;
于 2012-10-30T18:42:02.797 回答
0

您不能为基本类型“重载/添加”运算符,但可以为您的 type Type。但这不应该是operator =-operator >>就像在istreams 中一样。

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;
于 2012-10-30T17:48:24.600 回答