I have a little problem with one of my task for exercise for exam. This is a text:
Class MyFloat have a private variable float num. You have to write methods which will enable next lines of code:
MyFloat x = 3.5;
MyFloat y = x + 3.2
float z = 3.4 + y
And I write this code:
#include <iostream>
#include <Windows.h>
using namespace std;
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
MyFloat operator+(MyFloat x)
{
float result;
result = x.num + this->num;
return result;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4 + y;
system("PAUSE");
}
I get error in this line:
float z = 3.4 + y;
It says:
error C2677: binary '+' : no global operator found which takes type 'MyFloat' (or there is no acceptable conversion)
What should I do? How to solve this problem???
Implement operator+ as non-member friend function with 2 arguments MyFloat operator+(MyFloat x, MyFloat y).
Why doesn't it work in the current version? Because member operator functions are called on the objects on the left side of the operator. In your case on the left side you have integer literal which is not an object so lacks MyFloat operator+(MyFloat x) member function.
Non-member variants of operators are symmetrical and do not require the left side being an object. Symmetricity is important because as you see in your example operator+ is not symmetrical as we are used to think in math
Edit: But this is still not enough as noted by Cassio Neri in comments. Why? See his answer for the explanation but in short: you have ambiguity problems. You can use either his solution or this one if you do manual casting like this: float z = 3.4f + static_cast<float>(y); which is quite ugly. You can use another cast: float z = MyFloat(3.4f) + y if you provide MyFloat::operator float conversion.
Another solution to solve the same ambiguity problem: In C++11 you could use your own suffix literal (similar to f prefix for built-in floats, for example 3.4_f; (underscore means that this suffix literal is user-defined). Sample implementation (given that you implement operators for casting from MyFloat to float and backwards:
MyFloat operator "" _f(long double val) {
return MyFloat(static_cast<float>(val)); }
int main() {
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4_f + y;
}
This can be a solution:
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
operator float() const {
return num;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2f;
float z = 3.4f + y;
}
Initially, I also though about making MyFloat operator+(MyFloat, MyFloat) a non-member friend function but it still doesn't make the line
float z = 3.4 + y;
to compile. The reason is that 3.4 + y will be of type MyFloat and therefore you can't assign it to float z unless you provide a converting operator from MyFloat to float. Buth then, 3.4f + y becomes ambiguous (at least for VS 2010) because it can either call MyFloat operator+(MyFloat, MyFloat) or it can convert y to float and use the built-in operator + for floats.
You only have MyFloat + float operation, and you need to define float + MyFloat operation too. They are not the same.
Add this to your public functions:
friend float operator+ (const float& lhs, const MyFloat& rhs);
And this outside the class:
float operator+ (const float& lhs, const MyFloat& rhs) {
return lhs + rhs.num;
}
Note: Edited as per comment by CassioNeri.
While you can proceed with the answer where you define the "cast to float" approach, I believe it is better for your own sake that you start making use of your public API to implement additional behavior.
In general, a simple "casting" will not do the trick (for example, what happens if MyFloat were MyMatrix?).
The approach below is certainly more verbose, but it stresses that you should "eat your own food", meaning that you should try to implement additional behavior based on your own public interface, rather than a bunch of obscure implicit casts, or friend functions. If you use your own API: You will understand its limitations, and may potentially save recompilation of the main class if you make modifications.
Also, suppose that you wanted to count the accesses to your class (or otherwise control access to the underlying value): using the casting operator you would need to duplicate the code in operator float() and in float value().
So, here is my humble suggestion which appears longer but, to my taste, better reflects OO design principles.
#include<iostream>
class MyFloat {
public:
MyFloat(float value):
m_value(value) { }
float value() const {
return m_value;
}
private:
float m_value;
};
// Eat your own food: implement functions using your public interface
// until proven need to do otherwise. This will help you assess the
// usability of your API.
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); }
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; }
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); }
// See, now I can define another operator without need to recompile my
// class (this could have been placed in another file)
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) {
os<<"MyFloat("<<mf.value()<<")";
return os;
}
int main() {
MyFloat x = 3.5; // would not work if I had declared the constructor as "explicit"
MyFloat y = x + 3.2;
MyFloat z = 3.4 + y;
std::cout<<x<<", "<<y<<", "<<z<<std::endl;
}
Output (compiled with g++ example.cpp -Wall -Wextra):
MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)
Related
I want to add 2 objects, by overloading the + operator, but my compiler says there's no matching function to call to point::point(int, int). Can somebody please help me with this code, and explain the error ? thank you
#include <iostream>
using namespace std;
class point{
int x,y;
public:
point operator+ (point & first, point & second)
{
return point (first.x + second.x,first.y + second.y);
}
};
int main()
{
point lf (1,3)
point ls (4,5)
point el = lf + ls;
return 0;
}
You can just change your code like this,
#include <iostream>
using namespace std;
class point {
int x, y;
public:
point(int i, int j)
{
x = i;
y = j;
}
point operator+ (const point & first) const
{
return point(x + first.x, y + first.y);
}
};
int main()
{
point lf(1, 3);
point ls(4, 5);
point el = lf + ls;
return 0;
}
Hope this helps...
class point{
int x,y;
public:
point& operator+=(point const& rhs)& {
x+=rhs.x;
y+=rhs.y;
return *this;
}
friend point operator+(point lhs, point const& rhs){
lhs+=rhs;
return lhs;
}
};
There are a pile of little tricks above that make following this pattern a good "no brainer".
You get both += and + with the "proper" semantics.
If you chain +s together, you get elision of the left hand side operation. (ie, a+b+c becomes (a+b)+c, the return value of a+b is elided into the _+c call). If your objects have movable state, the proper moves happen for no design cost.
a+b works if either a or b is a point, and the other has an implicit-conversion-to-point. Member operator+ does not do this if a is not a point; this is pointless asymmetry.
a+=b is often more efficient to implement than a=a+b. When you implement += here, you get an efficient + as well. And your += is in turn defined in terms of member variable +=s.
The error with gdb I get is
main.cpp:8:49: error: ‘point point::operator+(point&, point&)’ must take either zero or one argument
This is because the the object that you plan to perform the operation on is this (the left hand side) and then the right hand side is the argument. If you wish to use the format that you've taken, then you can put the declaration outside the class - ie
struct point
{
// note made into a struct to ensure that the below operator can access the variables.
// alternatively one could make the function a friend if that's your preference
int x,y;
};
point operator+ (const point & first, const point & second) {
// note these {} are c++11 onwards. if you don't use c++11 then
// feel free to provide your own constructor.
return point {first.x + second.x,first.y + second.y};
}
I have a simple point class:
class Point {
public:
Point(const double, const double);
/** This constructor creates invalid point instance **/
Point();
~Point();
const double x;
const double y;
/** This returns true if one of the values is NaN **/
bool isInvalid() const;
/** Returns true if coordinates are equal **/
bool equal(const Point& p) const;
};
Values x and y are const so that I can be sure they never change. They are supposed to be always constant. The problem is I can't assign to variables holding Point:
Point somePoint;
... meanwhile, things happen ...
//ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
somePoint = Point(x, y);
I understand that assigning is a problem because somePoint.x = something is forbidden. I need to use point to hold last point value during rendering:
Point lastPoint;
PointInGraph* point = graphValues.last;
while((point = point->next())!=nullptr) {
// calculate pixel positions for point
double x,y;
...
if(!lastPoint.isInvalid())
drawer.drawLine(round(lastPoint.x), round(lastPoint.y), round(x), round(y));
// ERROR: use of deleted function 'Point& Point::operator=(const Point&)'
lastPoint = Point(x, y);
}
So does const in class properties simply make any variable of that class type const as well? Or is there a workaround?
It's not possible. It would require modifying const values.
Instead of making x and y themselves const, make them non-const but provide a const interface to them, i.e. by making them private and providing const getters.
Instead of making the variables const you could just not provide any way for the user to change the values by:
making them private
only allowing assignment to a another instance as the only way to change the values.
You can see how this would work in the following example:
#include <iostream>
class Point {
public:
Point(const double x_ = 0, const double y_ = 0) : x(x_), y(y_) {}
double getX() const { return x; }
double getY() const { return y; }
private:
double x;
double y;
};
int main()
{
Point a{1,5};
Point p;
p = a;
std::cout << p.getX() << ", " << p.getY(); // no error here
//p.x = 5; // error here now
//p.y = 7; // error here now
}
Live Example
If you un-comment the last two lines you will get an error to prove that you cannot change x and y.
Actually it's, of course, possible by directly technique called cast away constness which is a known loophole in const mechanic in C++. Basically I can abuse the fact that const int* can be assigned to int* variable. The possible solution:
Point& Point::operator=(const Point& p)
{
*((double*)&x)=p.x;
*((double*)&y)=p.y;
}
This is of course not recommended, but I'm not the one of the people who think that knowledge is dangerous.
I have a class which is essentially an array with labelled contents, and I'd like to define some operators for it. I'd like to do it in such a way that changing the number of elements in the class is easy, as I expect future users will change the variables tracked, but I'd also like to ensure that basic arithmetic operations on the class are as efficient as possible.
I can see two way of implementing the operators. Taking the example of a Vector2D class:
struct Vector2D {
//members
const static int nElem = 2;
double x;
double y;
//Constructors
Vector2D() {}
Vector2D(double X, double Y) : x(X), y(Y) {}
//Operators
double& operator[] (int index) {
switch(index) {
case 0:
return x;
case 1:
return y;
default:
return std::out_of_range ("Oops");
}
}
// Option 1: operator+ by constructing result
Vector2D operator+ (const Vector2D & rhs) const {
return Vector2D(x + rhs.x, y+rhs.y);
}
// Option 2: operator+ using loop and [] operator
Vector2D operator+ (const Vector2D & rhs) const {
Vector2D result;
for(int i = 0; i < nElem; i++)
result[i] = (*this)[i] + rhs[i];
return result;
}
};
Assuming I use -03 optimization, will there be any difference between the two implementations of operator+? My understanding is that since the default Vector2D constructor has no code body and the class contents are a default data type, there is no extra overhead in Option 2 for calling the default constructor on result before setting its members. I expect the two to be equivalent, but I'm not confident enough in my knowledge to be sure.
Your method won't work at all. If you want someone to be able to change nElem you can't use x, y as your names. Why? Because changing nElem to 3 won't magically add z. And since you can't do a for loop over x and y, your definition of nElem is meaningless.
Finally, this is a textbook case for the use of a number template. Create a vector which is templated over how many elements it has.
Do something like this:
template<unsigned int LEN>
class Vector{
double v[LEN];
public:
Vector operator+(const Vector &o){
Vector res;
for (unsigned int i=0;i<LEN;++i) // with -O3 and small LEN this will be unrolled
res.v[i]=v[i]+o.v[i];
}
// ... etc.
};
Then you use it like this:
Vector<2> my_2d_vec;
Vector<3> my_3d_vec;
I have a class called Coord...it has instance data x, y. I want to override the * operator such that the * operator can be used to multiply the Coord by an integer or double! This is the solution I put up:
Coord& Coord::operator*(int n)
{
this->x = this->x*n;
this->y = this->y*n;
return *this;
}
It works - I've tested some print outs from main...the only issue is...I get a warning from the -Weffc++ flag! It says my function should return by value! I know this flag corresponds to the book "Effective C++" book, but I don't have a copy onhand - what does the book suggest? What is meant to pass by value?
Just to elaborate on Grizzly's comment... This is not the in-place multiplication. As such, you should declare it const to explicitly prevent that:
Coord Coord::operator*(int n) const {
Coord c(*this);
c.x *= n;
c.y *= n;
return c;
}
Or if you have a useful constructor:
Coord Coord::operator*(int n) const {
return Coord(x*n, y*n);
}
The in-place multiplication is different (and non-const):
Coord& Coord::operator*=(int n) {
x *= n;
y *= n;
return *this;
}
You haven't implemented operator* but rather you implemented the self-mutating operator*=, assigning the result back to the original object.
Consider the effects of your operator's implementation for the following int example:
int x = 5;
int y = 2;
int z = x * y;
Now, with integer multiplication implemented similarly to your code, you would end up with both y and z equal to 10.
In order to implement the normal operator* type operators you'll need to create a temporary object and return that by value.
You're probably looking for an implementation more like this (assuming you have a two parameter constructor to your class):
Coord Coord::operator*(int n) const
{
return Coord(x * n, y * n);
}
But note that often, what seems like an obvious meaning of an operator isn't so clear, and overloading simply causes confusion. Consider a non-member named function instead (using a named member scaling function), along these lines:
Coord& Coord::ScaleBy(int n)
{
this->x = this->x*n;
this->y = this->y*n;
return *this;
}
Coord ScaleCoord(Coord c, int n)
{
return c.ScaleBy(n);
}
In general, this sort of thing is done in two parts, a member operator*= and a non-member operator* that uses *=:
Coord& Coord::operator*=(int n) {
x *= n;
y *= n;
return *this;
}
Coord operator*(const Coord& c, int n) {
Coord res(c);
res *= n;
return res;
}
the question may look silly ,but i want to ask..
Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
#DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
less wordy
function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Long example with actual usecase *
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
Short example for demonstration *
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.