VenkateshJN
VenkateshJN

Reputation: 2174

Structures and Operator Overloading in C++

struct PT 
{   
  double x, y;  
  PT() {}  
  PT(double x, double y) : x(x), y(y) {}  
  PT(const PT &p) : x(p.x), y(p.y)    {}  
  PT operator + (const PT &p)  const { return PT(x+p.x, y+p.y); }  
  PT operator - (const PT &p)  const { return PT(x-p.x, y-p.y); }  
  PT operator * (double c)     const { return PT(x*c,   y*c  ); }  
  PT operator / (double c)     const { return PT(x/c,   y/c  ); }  
};

This code snippet is from http://stanford.edu/~liszt90/acm/notebook.html#file8 . I am not able to understand this piece of code . Someone please explain this . I know that this is operator overloading but am not able to understand how exactly operator overloading is taking place.

Can someone explain these lines also:

PT() {}  
PT(double x, double y) : x(x), y(y) {}  
PT(const PT &p) : x(p.x), y(p.y)    {}

Do structures also have constructors ?

Upvotes: 2

Views: 7450

Answers (5)

6502
6502

Reputation: 114559

Probably it's easier to understand operator overloading by looking at the non-member version of it. If you want to tell the compiler what do you mean by adding two PT objects you can write the following:

PT operator + (const PT& a, const PT& b)
{
    return PT(a.x + b.x, a.y + b.y);
}

the above code simply says that when the compiler finds the expression a + b where both a and b are PT instances then the result is a new PT instance computed by that function.

You can do the same for a few other operators and thanks to this you can make your class instances to behave more "naturally" in respect to normal math.

The code you've is the same but written in a somewhat unnatural asymmetric form where you describe what to do when another object is for example added to this object. Such an approach looks quite strange for binary math operators because for example there's nothing special in the first or second operand of an addition and they're both on the same logical level. The asymmetry for the this concept is however part of the C++ DNA and there's nothing much you can do about it. In theory it's a bad asymmetry for any method that takes even just a parameter but in practice you can still go for quite a while even with this approach.

Other parts of the code are:

// Default constructor. Will create an object without any parameter
// and the x, y values will be uninitialized. This is generally a bad
// practice and you should avoid it unless there are very specific and
// measured performance reasons for doing that.
// Having a constructor accepting no parameters is sometimes necessary
// if you want for example to be able to put your instances in an std::vector
// and you may need to call .resize() on the vector. Even if you will always
// just shrink the vector the compiler will require anyway a default
// constructor because there's no shrink-only call on vectors and any
// resize operation is assumed to be potentially growing the size.
PT() {}

// Copy constructor. This is totally unneeded... when you don't
// put a copy constructor in a class the C++ compiler will automatically
// generate exactly this code (i.e. a constructor that will copy-construct
// all members). In general this may be or may not be the right thing
// depending on the class, but in this case is exactly what you want
// and there was no need for this code.
// As a general rule if you see a copy constructor, an assignment operator
// or a destructor but you don't see all three of them in a class then
// most probably there's something wrong. It's difficult to think to
// a real use case in which you need some of them but not all three of
// them... in this case for example the mistake is that this code could
// and should have been omitted.
PT(const PT &p) : x(p.x), y(p.y) {}

Upvotes: 0

Michael J
Michael J

Reputation: 7939

double x, y;  

Declares two local, class variables that make up the class.

PT() {}  

Default constructor. Allows you to create a PT without any arguments.
e.g. --> PT myObj;

PT(double x, double y) : x(x), y(y) {}  

Constructor to create a point from two doubles.
e.g. --> PT myObj(3.5, 9.0);
After the declaration --> PT(double x, double y) : x(x), y(y) {}
we have initialisation .--> PT(double x, double y) : x(x), y(y) {}
x(x) is equivalent to this->x = x;
i.e. initialise the class variable 'x' with the constructor parameter 'x'. It is somewhat confusing that they have given the parameters the same name as the class variables. A better example might have been:

    PT(double xInit, double yInit) 
    : x(xInit)
    , y(yInit) 
    {
    }  



    PT(const PT &p) : x(p.x), y(p.y)    {}  

Copy constructor to create a PT object from another PT object
e.g. --> PT myOtherObj(myObj);

PT operator + (const PT &p)  const { return PT(x+p.x, y+p.y); }  
PT operator - (const PT &p)  const { return PT(x-p.x, y-p.y); }

Addition and subtraction operators to get the sum or difference of two points to make a third.
e.g. -->

    PT sumObj  = myObj + myOtherObj;
    PT diffObj = myObj - myOtherObj;



PT operator * (double c) const { return PT(x*c, y*c ); }
PT operator / (double c) const { return PT(x/c, y/c ); }

Multiplication and division operators to multiply (or divide) a point by a constant.
e.g. -->

    PT prodObj = myObj * 2.7;
    PT divObj  = myObj / 8.0;

Upvotes: 2

CapelliC
CapelliC

Reputation: 60034

Lines 4 & 5 are constructors, and the syntax x(x) highlights an idiomatic way to invoke constructor of the member variables (pass down, to say).

Note that is not required a different identifier for a formal parameter. Assign from inside the body of the constructor would require a different naming, because a formal parameter 'hides' the member variables. I.e. we would need, for instance

 PT(double x_, double y_) { x = x_; y = y_; }  

Also note that this way we are not calling the constructor of member x, but the assignment operator. There is no difference for POD data, but the syntax allows for arbitrary, user defined, member functions on classes like PT.

Upvotes: 1

iammilind
iammilind

Reputation: 70030

Operator overloading is a concept where the usual operators like +, '-, '*, ... are 'overloaded' for structure/classes also. Generally this facility is available only to the original data types like int, double, ....

Here in struct PT, the operator methods are simply defined. It will kick-in once you declare the object of PT and start using it. e.g.

PT pt1, pt2;
PT pt3 = pt1 + pt2;  // pt1.operator +() has instantiated

Upvotes: 0

Joel Falcou
Joel Falcou

Reputation: 6357

Whenever the compiler encounters a call of the form

a + b;

it actually calls

a.operator+(b)

if such method exists in the type of a or

operator+(a,b)

if such a free function exists.

The operator??? syntax is just saying that you are currently overloading said operator ??? (For any valid ??? of course).

Upvotes: 0

Related Questions