Archived

This topic is now archived and is closed to further replies.

Tevong

overloading operators?

Recommended Posts

I''m doing this exactly the same way the book has done it but i keep getting errors. Since I''m new to this I don''t know where to start debugging. Here''s the class in which I declare the operator thing: class CVehicle //no base classes { friend class CWeathersystem; private: unsigned int weight,capacity; float topspeed; public: void printdata(); //constructors and destructors CVehicle(); ~CVehicle(); unsigned int getweight(){return weight;} unsigned int getcapacity(){return capacity;} float gettopspeed(){return topspeed;} int setweight(unsigned int newweight); int setcapacity(unsigned int newcapacity); int settopspeed(float newtopspeed); CVehicle operator + (CVehicle right); //<----------here }; Here''s the function: inline CVehicle CVehicle::operator + (CVehicle right) { return CVehicle(weight+right.weight,capacity+right.capacity, topspeed+right.topspeed); } I dont'' see what''s wrong with this. All it does is return the added weight, topspeed and capacity of the 2 vehicle objects.

Share this post


Link to post
Share on other sites
hm... what error does the compiler give you ?

Anyway, I don''t think you can specify the inline keyword outside the class declaration. Try something like this :

  

class CVehicle
{

// stuff...


inline CVehicle CVehicle::operator + (CVehicle right)
{
return CVehicle(weight+right.weight,capacity+right.capacity,
topspeed+right.topspeed);
}
};


Share this post


Link to post
Share on other sites
You need another constructor with which to create the vehicle you are returning.

CVehicle(int weight, int capacity, float topspeed);

You probably want to rename the members so they can be distinguished from parameters - ie m_weight etc.

CVehicle (int weight, int capacity, float topspeed)
:m_weight(weight), m_capacity(capacity), m_topspeed(topspeed)
{
}

Share this post


Link to post
Share on other sites
quote:
Original post by Prosper/LOADED
hm... what error does the compiler give you ?

Anyway, I don''t think you can specify the inline keyword outside the class declaration. Try something like this :



Actually you can. Functions written inside the class declaration are automatically considered "inline". If you want a member function to be inline but the code for it elsewhere it''s perfectly valid to use inline outside the class. However, there is no guarentee that functions will be expanded as inline.


-------
Andrew

Share this post


Link to post
Share on other sites
How would you define the << operator with the ostream class, so you could do something like this:

  
CCustomClass class;
cout << class;

ofstream fout;
fout.open("debug.txt");

fout << class;
fout << flush;
fout.close();


without getting where it''s stored in memory (0xABCDEF12 or something)?

Share this post


Link to post
Share on other sites
Here''s a simple example on how to overload the << operator.

  
class Point
{
public:
Point() : x(0), y(0){;}
int x;
int y;
};

//Overload the << operator when dealing with Point

ostream& operator<< (ostream& os , Point& p)
{
os << p.x;
os << p.y;
}

int main()
{
Point p;
ofstream fout;
fout.open("debug.txt");
// Out to screen.

cout << p;

//Out to file.

fout << p;
fout << flush;
fout.close();
}


-------
Andrew

Share this post


Link to post
Share on other sites
quote:
Original post by brad_beveridge
It looks like you have a space between the word operator and the symbol +

You need operator+ (Cvehicle...)

Sorry, not true. operator is a keyword just like any other in C++. The help for operator says the following:
quote:
from MSDN

operator


C++ Specific —>

type operator operator-symbol ( parameter-list )

The operator keyword declares a function specifying what operator-symbol means when applied to instances of a class. This gives the operator more than one meaning, or "overloads" it. The compiler distinguishes between the different meanings of an operator by examining the types of its operands.

C++ (and C) ignores whitespace.

The problem is the distinction between binary and unary operators. + is both binary and unary (a + b <- binary; +b <-unary). Unary + is useless for most pseudo-arithmetic types (it doesn''t change the value: +(-3) is -3). Binary + cannot be implemented as a member function since it needs two objects and returns a third. You can make += a member function, though, since it modifies the left-hand parameter:

class CVehicle
{
...
public:
inline CVehicle &operator += (CVehicle &v);
friend CVehicle &operator + (CVehicle &v1, CVehicle &v2);
};
//
// compiler will attempt to make this inline
CVehicle &CVehicle::operator += (CVehicle &v)
{
weight += v.weight;
capacity += v.capacity;
topspeed += v.topspeed;
//
// return the modified object
// note that ''this'' is a pointer so it must be dereferenced.
return *this;
}
//
// note that opertor+ is not a member function
CVehicle &operator + (CVehicle &v1, CVehicle &v2)
{
CVehicle v; // uses default constructor; better have one!
//
// operator + can access private data member because it is a
// friend function:
v.weight = v1.weight + v2.weight;
v.capacity = v1.capacity + v2.capacity;
v.topspeed = v1.topspeed + v2.topspeed;
//
// return the result of the addition
return v;
}

You could have used a different constructor for v in operator+ above (CVehicle v(v1.weight + v2.weight, v1.capacity + v2.capacity, ...)).

Oh, and use whitespace liberally. As I''ve noted, C++ ignores it so it makes code nicer to look at and read.

Share this post


Link to post
Share on other sites
Err - I am not sure that that is true?

The operator+ is associated with the lhs parameter so it only takes one parameter - the rhs.

Share this post


Link to post
Share on other sites
To elaborate (unnecessarily ) on the binary operator thing:

If the first operand of an operator is an object, then that operator can reside in the class of that object, but if the first operand is a builtin-type, or a class-type that you cannot change the declaration for, then you must declare the operator as a global functions.

e.g. consider a vector class that must have the binary multiplication defined for multiplying a scalar with the vector:
  
class Vector
{
float x, y, z;

// The following can only accomodate invocations of the form:

// vector * scalar

const Vector operator * (const float s)
{
return Vector(x*s, y*s, z*s);
};

// A global friend operator accomodates invocations of the form:

// scalar * vector

friend const Vector operator * (const float s, const Vector &v);
};

// global operator (scalar * vector)

const Vector operator * (const float s, const Vector &v)
{
return v * s; // return v.operator * (s);

};

(the rest of the class was omitted for brevity)

Share this post


Link to post
Share on other sites
As Gillies stated you only need a new constructor for the operator overloader function as follow:

  
CVehicle(unsigned int c_weight, unsigned int c_capacity, float c_topspeed);

CVehicle(unsigned int c_weight, unsigned int c_capacity, float c_topspeed) : weight(c_weight), capacity(c_capacity), topspeed(c_topspeed) { }


And the code will work as it should.
But since you almost always want to initialize the values one way or the other I would remove the CVehicle() constructor and replace it with this one that use default values:

  
CVehicle(unsigned int c_weight = 0, unsigned int c_capacity = 0, float c_topspeed = 0.0f);



Edited by - errand on October 24, 2001 7:31:06 AM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
you can make the binary + a member function, just only have one parameter. However it is considered better form to have it be a non member function and implement it in terms of +=. That way it lets implicit constuctors work on the left operand

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
you can make the binary + a member function, just only have one parameter.

I looked that up, and he''s right. Thanks!

quote:
However it is considered better form to have it be a non member function and implement it in terms of +=. That way it lets implicit constuctors work on the left operand

I think it''s a bad idea to implement operator+ in terms of operator+=, because a + normally takes its lhs and rhs operands, adds them together and returns the sum without modifying either of them. If you''re speaking of using operator+= on the sum object, well isn''t that inefficient? Consider:

// using += on one of the operands:
myclass &operator+(myclass &m1, myclass &m2)
{
m1 += m2;
return m1;
}
// this has the effect of making c = a + b set c to the sum, but
// a to the sum as well.
//
// using += on the sum object:
myclass &operator+(myclass &m1, myclass &m2)
{
myclass m;
m += m1;
m += m2;
return m;
}
// this is just plain stoopid.
//
// what I consider to be the best way for pseudo-arithmetic types:
myclass &operator+(myclass &m1, myclass &m2)
{
mylcass m;
m = m1 + m2; // this would actually be a + on the individual fields,
// such as the coordinates in a vector
return m;
}
// c = a + b behaves properly.

Alternatively, as a member function:

myclass &myclass::operator+(myclass &m)
{
myclass r = *this;
r += m;
return r;
// 2 assignments, an extra copy of r and one addition.
// compare to one copy of the sum, one addition and one assignment for friend version
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
well that''s what I''ve read Stroustrup''s book and he seems like a really smart guy (plus he made the language) so I''m doing it his way. I think it was something like this

A operator+(A l, A r)
{
return l+=r;
}

or maybe this

A operator+(A& l, A& r)
{
A a = l;
return l+=r;
}

I think it was the first one so that implicit constructors would work. I''m not sure but I don''t think they would work if you use a reference. So if you have a type B and a constructor A(B) you could do b+a with the first one. If it were a member function you would have to always do a+b.

Another reason so implementing + in terms of += is that they always stay the same. You only need to change += and they both change. Also since += is a member function it will have access to private members while binary+ won''t (though of course you can almost always make it a friend). If += is inlined into + it should be about the same speed anyway I think.

Share this post


Link to post
Share on other sites