更简单的方式让类与运算符一起工作?

3

这里有一个名为Value的类,它可以简单地获取和设置float

class Value
{
public:
    Value(float f)
    :f(f){};
    float get()
    {
        return f;
    }
    void set(float f)
    {
        this->f = f;
    }
private:
    float f;
};

我希望我的类能够像下面的例子一样工作。
Value value(3);
std::cout << value * 2 - 1 << std::endl; // -> 5
std::cout << value == 5 << std::endl; // -> true
value /= 2; 
std::cout << value << std::endl; // -> 2.5

我应该手动将所有操作符方法添加到我的类中吗?

还是有更简单的解决方案可以像处理float一样对待Value


3
请对转换运算符进行一些研究。请注意,这样的类通常会使代码更难阅读、理解和维护。 - Some programmer dude
1
值得一提的是,同时具有隐式转换为或从float的能力可能会在某些情况下导致歧义。 - StoryTeller - Unslander Monica
就目前而言,你的“Value”类只是一个更麻烦使用的“float”。我不确定你是否需要它*。 - Caleth
无论你做什么,你都必须加上括号 value == 5(即 (value == 5))。 - Paul Sanders
@Caleth 或许这只是一次实验。 - Paul Sanders
3个回答

3

与其使用get(),你可以使用类型转换运算符将其转换为float类型:

operator float() const { return f; }

如果您还想启用更改值的操作(例如/=),可以使用类似的非const运算符返回引用,或者手动添加这些运算符。但是,如果您想要一个与float完全相同的类,最好使用float而不是完全使用Value类。

1
我实现了/===运算符:

你可以使用这个页面来学习更多... https://www.tutorialspoint.com/cplusplus/cpp_overloading.htm

class Value
{
public:
    Value(float f) : f(f) {};

    operator float() const
    {
        return f;
    }

    void set(float f)
    {
        this->f = f;
    }

    Value &operator /=(float num)           // e.g. value /= 2;
    {
        this->f = f / num;
    }

    bool operator==(const float& a) const    // e.g. std::cout << value == 5 << std::endl; // -> true
    {
        if(this->f == a) return true;
            return false;
    }

private:
    float f;
};

主函数:
int main()
{
   Value value(10);

    value /= 5;

    cout << value << endl;
    cout << (value == 5) << endl;

return 0;
}

operator /= 应该返回 Value&。请参见 https://dev59.com/uF3Ua4cB1Zd3GeqP-TMU - VLL
@Ville-Valtteri 是的,我改进了它...谢谢。 - BattleTested_закалённый в бою

1
这是相关算术、相等和流操作的惯用实现。
注释中有说明。
还请注意允许从float进行隐式转换的后果/好处。
#include <iostream>

class Value
{
public:
    // Note - this constructor is not explicit.
    // This means that in an expression we regard a float and a Value on the
    // right hand side of the expression as equivalent in meaning.
    // Note A.
    //      =
    Value(float f)
    :f(f){};

    float get() const
    {
        return f;
    }

    void set(float f)
    {
        this->f = f;
    }

    // Idiom: unary operators defined as class members
    // 
    Value& operator *= (Value const& r)
    {
        f *= r.f;
        return *this;
    }

    Value& operator -= (Value const& r)
    {
        f -= r.f;
        return *this;
    }

    Value& operator /= (Value const& r)
    {
        f /= r.f;
        return *this;
    }

private:
    float f;
};

// Idiom: binary operators written as free functions in terms of unary operators

// remember Note A? A float will convert to a Value... Note B
//                                                          =
auto operator*(Value l, Value const& r) -> Value
{
    l *= r;
    return l;
}

auto operator-(Value l, Value const& r) -> Value
{
    l -= r;
    return l;
}

auto operator<<(std::ostream& l, Value const& r) -> std::ostream&
{
    return l << r.get();
}

// Idiom: binary operators implemented as free functions in terms of public interface
auto operator==(Value const& l, Value const& r) -> bool
{
    return l.get() == r.get();
}

int main()
{
    Value value(3);
    // expressions in output streams need to be parenthesised
    // because of operator precedence
    std::cout << (value * 2 - 1) << std::endl; // -> 5
    // ^^ remember note B? value * 2 will resolve to value * Value(2) because of
    // implicit conversion (Note A)
    std::cout << (value == 5) << std::endl; // -> true
    value /= 2; 
    std::cout << value << std::endl; // -> 2.5
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接