问题
Here, I have a class called Value
which simply can get and set float
.
class Value
{
public:
Value(float f)
:f(f){};
float get()
{
return f;
}
void set(float f)
{
this->f = f;
}
private:
float f;
};
And I want my class to be able to work like the following example.
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
Should I manually add all operator methods to my class?
Or would there be any easier solution to treat Value
like float
?
回答1:
Here is an idiomatic implementation of the relevant arithmetic, equality and stream operators.
Notes in the comments inline.
See also the note about the consequences/benefits of allowing implicit conversion from 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
}
回答2:
Instead of get()
, you could have a conversion operator to float
type:
operator float() const { return f; }
If you also want to enable operations that change the value (such as /=
), you can have similar non-const operator that returns a reference, or you can add those operators manually.
But if you want to have a class that behaves exactly like float
, it might be better to use float
instead of having the Value
class at all.
回答3:
I implemented /=
and ==
operators :
you can use of this page for learn more... 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;
};
main :
int main()
{
Value value(10);
value /= 5;
cout << value << endl;
cout << (value == 5) << endl;
return 0;
}
来源:https://stackoverflow.com/questions/51239390/easier-way-to-make-class-to-work-with-operators