I want to overload the % operator in c++, in order to avoid editing a huge block of code by hand. I tried this:
static float operator %(const float& left, const float& right);
In my header, but it wont work because "nonmember operator requires a parameter with class or enum type".
I'm relatively new to C++, what am I supposed to do?
Operator overloads must have at least one of their arguments as a user-defined type. So you cannot do this.
What that means is that you cannot overload an operator when all the operands are non-class/enum types. i.e., you cannot override the behaviour of % when both sides are float (or int, or any other primitive type).
As has already been stated, you cannot define overloaded operators for intrinsic types.
However, if you are willing to take advantage of implicit type conversion you can achieve something close to what you require with a single cast to one of your floats on a wrapper type that implements an overloaded% operator.
class FloatWrapper
{
private:
float m_Float;
public:
FloatWrapper(float Value):
m_Float(Value)
{
}
friend float operator%(const FloatWrapper& lhs, const FloatWrapper& rhs)
{
//your logic here...
return (int)lhs.m_Float % (int)rhs.m_Float;
}
};
int main()
{
float Value1 = 15.0f;
float Value2 = 4.0f;
float fMod1 = (FloatWrapper)Value1 % Value2;
float fMod2 = Value1 % (FloatWrapper)Value2;
return 0;
}
class Test
{
public:
float operator%(float);
};
In C++ you need not to declare the operator as static, as opposed to C#. The argument can be of any type and the return value can also be. The first type would be the class itself.
Example:
Test test;
float x = test % 10.2f;
Related
Take this for example:
float operator+(int a, float b)
{
Return b + (float)a;
}
void main()
{
int a = 10;
float b = 2.5f;
float c;
c = a + b; //works as intended
c = b + a; //results in type mismatch error
}
So my question:
Is there a way to have the parameters being accepted bidirectional without defining a second function?
It is not possible to overload operators for fundamental types.
You should only overload operators for classes that you have defined.
A solution for overloading a binary operator for your own class with heterogeneous arguments symmetrically, is to define the operator for first type, and make the second type implicitly convertible to the first.
Use float 'a' instead of int 'a',In default when adding int number to float it automatically assign higher precision. (Int + float outcome become float)
I have been looking through source code trying to learn more about C++ and I came across some code that looked confusing. I haven't been able to figure out its use by playing around with it.
Please can someone explain what the operator float *() does and how it is used?
class Vector
{
public:
float x,y,z;
Vector() : x(0), y(0), z(0){
}
Vector( float x, float y, float z ) : x(x), y(y), z(z){
}
operator float*(){
return &x;
}
operator const float *(){
return &x;
}
I have searched StackOverflow and it looks like it is a conversion operator but I am still unsure what it actually does and why it is useful.
Kind regards,
operator type_name declares an implicit conversion operator. In other words, this function is called when you are attempting to (implicitly) convert an object of your type to float* – for instance in an assignment:
Vector x(1, 2, 3);
float* f = x;
assert(*f == 1);
Needless to say, this particular conversion is quite terrible because its effect is pretty unintuitive and easily results in impossible to find bugs. Implicit conversions should generally be handled with care since they hide potentially confusing semantics. But they can be used well with types which are supposed to be used interchangeably, and where a conversion doesn’t hurt.
For instance, consider the case where you write your own integer and complex classes. A conversion from integer to complex is harmless, since every integer is a complex number (but not vice-versa). So having an implicit conversion integer → complex is safe.
As it was said it is a conversion operator that converts an object of type Vector to an object of type float *. This conversion operator can be called implicitly because it has no function specifier explicit.
I think that the idea of introducing this operator was to access data members x, y, z as an array of floats. In this case you could apply some standard algorithms to an object of the class converting it to an array of floats.
Take into account that the second overloaded operator-function shall have qualifier const.
Consider the following code
#include <iostream>
#include <algorithm>
class Vector
{
public:
float x,y,z;
Vector() : x(0), y(0), z(0){
}
Vector( float x, float y, float z ) : x(x), y(y), z(z){
}
operator float*(){
return &x;
}
operator const float *() const {
return &x;
}
};
int main()
{
Vector v( 1, 3, 2 );
auto max = std::max_element( v + 0, v + 3 );
std::cout << *max << std::endl;
return 0;
}
The output is 3.
Take into account that according to the C++ Standard
13 Nonstatic data members of a (non-union) class with the same access
control (Clause 11) are allocated so that later members have higher
addresses within a class object
So the order of the data members of the class is defined.
It's a conversion operator allowing the class to be used with APIs that want a float*.You have two different versions because one will convert the class to a const float* and the other to a non-const. The non-const conversion operator breaks your class's encapsulation though.
Usefulness: Well it can be very handy when, as I mentioned, you want to work with a library that expects a certain type. It can also be useful when there is a natural conversion between two types.
PI'm trying to wrap float, int, etc primitves value into my SParam class. But I have some problem with getting values from this struct. I want to use this struct as I use for example floats.
template<class T>
struct SParam
{
T value;
SParam()
{
}
operator T() const
{
return value;
}
};
SParam<float> a;
a.value = 4;
printf("%f", a); //<--this don't print a.value
The problem with using the "naked" SParam<float> a with printf (or any other function that takes a variable number of arguments, for that matter) is that the compiler does not know that you want to pass a float. That is why the type-specific conversion is not applied. If you call a function with a specific parameter type, say
void printFloat(float f) {
printf("%f", f);
}
...
SParam<float> a;
a.value = 4;
printFloat(a);
then the compiler would figure out from the signature of printFloat that your conversion to float needs to be applied, and everything would work as expected. Of course you can always apply the conversion manually:
printf("%f", (float)a);
Because you need to call a() in the printf, not a.
a is just an object of type SParam, you'll probably need to modify the operator definition to specify a return type of T as well..
for comparison try using float x = a; it should give you an error. float x = a(); should not however
I have below class in VS2010-SP1, Ternary operator and if-else seems to be working differently for below code on getname method
template <int size=120> class StringBuf{
public:
StringBuf(const char* src){
strcpy(s,src);
}
// Copy from another StringBuf
StringBuf(const StringBuf& src){
strcpy(s,src.get());
}
// String access
operator const char*() const {return get();}
const char* get() const { return s ; }
private:
char s[size];
};
class MyPony{
StringBuf<10> name;
public:
MyPony(char* name_) : name(name_){}
const char* getname(bool bVal){
//if( bVal )
// return name;
//else
// return "Jimmy";
return (bVal==true) ? name : "Jimmy";
}
};
int main(){
MyPony pony("Pani");
const char* getname = pony.getname(true);
return 0;
}
If I use ternary operator getname() method makes a copy of name by calling copy constructor and then calls operator const char* on the temp copy.
If I change ternary operator into if-else the code just calls operator const char* without making a temp copy.
My understanding is that if else and ternary operator should behave the same, but why is this different behavior for this class? Is there something that I'm overlooking?
For ternary operator VS2005 seems to call operator const char* directly .
Of course: The type of the conditional expression a ? b : c is the common type of b and c, which in your case is StringBuf<10>. So either operand must first get converted to that type before the resulting value can be considered for return.
There conditional expression is an expression, and the if statement is a statement. They're different things for different purposes. Use the if statement in your situation.
You might wonder why the common type is StringBuf<10> and not char const *. That's because of C++11 5.16/3 ("Conditional operator"), which says that implicit conversions are considered. In your case, there is an implicit conversion from char const [6] (the type of "Jimmy") to StringBuf<10>, but not the other way round, so the common type is uniquely defined. For comparison, if you tried x ? name : static_cast<char const *>("Jimmy"), that would not compile.
I have a class employee
#include <iostream>
#include <string>
using namespace std;
class employee
{
public:
double operator + (employee);
employee(int);
double getSalary();
private:
double salary;
};
int main()
{
employee A(400);
employee B(800);
cout<<A+B;
employee C = A+B;
cout<<C.getSalary();
}
employee::employee(int salary)
{
this->salary = salary;
}
double employee::operator + (employee e)
{
double total;
total = e.salary + this->salary;
return total;
}
double employee::getSalary()
{
return this->salary;
}
I have overloaded the operator + so that it adds up the salary of 2 employee objects . The return type of the overloaded + operator is double.
This is my question
1) Why does employee C = A + B work when i have overloaded the operator + to return a double and not a employee , shouldnt there be a compiler error??
2) what is actually happening???
When you overload operator+ to return a double, the compiler will look at whether it can convert that double to an employee object. Since you have a ctor that takes an int, it does an implicit conversion from double to int, then uses your ctor to convert from int to employee.
So no, that shouldn't generate a compiler error.
At the same time, it doesn't make much sense. Right now, you've defined the employee's salary member as a double, but only allowed the user to specify an int to initialize it. You probably want to allow initializing it with a double instead.
As it stands right now, your operator+ also has asymmetric behavior: it can do implicit conversions on the right operand, but not on the left, so a + 1 works, but 1 + a doesn't.
You can eliminate all implicit conversions by making your conversion constructors (i.e., all that can be invoked with a single parameter) explicit. Conversely, you can allow implicit conversions on either a left or a right operand by implementing the overload as a free function:
employee operator+(employee const &a, employee const &b) {
return employee(a.salary + b.salary);
}
Since salary is private, you would/will have to declare this operator as a friend of the class for it to work.
You usually want to do one of these or the other. If implicit conversions make sense, then you probably want to support them on both operands. If they don't make sense, then you probably want to prohibit them entirely. The middle ground -- a + that can convert one operand but not the other rarely makes much sense.
Then again, I'd argue that supporting addition on employees doesn't make sense anyway. It would not be immediately obvious to me (or I think most readers) that adding two employees would yield a third employee object containing the sum of the two employees' salaries, with the rest of the data invalid. In fact, I'd argue that you probably shouldn't allow creation of such an invalid employee object at all.
It works because you have specified this constructor:
employee(int);
Although you will receive a warning about possible loss of data when converting from double to int. So when compiler sees the double, it checks if there is any constructor taking a double parameter. To make it not work specify your constructor as explicit:
explicit employee(int);