Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Operator Overloading in C++: Implementing the Money Class with +, ==, <, and << Operators, Lecture notes of C programming

Operator overloading in C++ and demonstrates how to implement the Money class with the +, ==, <, and << operators. The code includes the header file, implementation file, and an example application program. Overloading operators as member functions is advocated for better encapsulation and easier implementation.

What you will learn

  • What are the common operators to overload in the Money class?
  • What are the potential issues when overloading the == operator in the Money class?
  • Why is it important to follow the syntax rules when overloading operators?
  • What are the advantages of overloading operators as member functions?
  • How do you declare and implement an operator function in C++?

Typology: Lecture notes

2021/2022

Uploaded on 09/12/2022

prouline
prouline 🇬🇧

4.6

(7)

221 documents

1 / 15

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
OPERATOR OVERLOADING
Fundamentals
There are many operators available that work on built-in types,
like int and double.
Operator overloading -- is the creation of new versions of these operators for
use with user-defined types.
Operators usually refer to C++ predefined operators:
o arithmetic operators: +, -, *, /, %
o relational operators: <, <=, ==, !=, >, >=
o assignment operator: =
o logical operators: &&, ||, !
o input/output operators: <<, >>
It is not as difficult as it sounds. Some things to note:
o An operator in C++ is just a function that is called with special
notation (usually more intuitive or familiar notation). Overloading an
operator simply involves writing a function.
o C++ already does some operator overloading implicitly on built-in
types. Consider the fact that the + operator already works for ints,
floats, doubles, and chars. There is really a different version of the +
operator for each type.
Operator overloading is done for the purpose of using familiar operator notation
on programmer-defined types (classes).
Some rules regarding operator overloading
Overloading an operator cannot change its precedence.
Overloading an operator cannot change its associativity.
Overloading an operator cannot change its "arity" (i.e. number of operands)
You cannot change the number of arguments that an operator takes.
It is not possible to create new operators -- only new versions of existing
ones.
Operator meaning on the built-in types cannot be changed.
The following operator can only be overloaded as member functions: =, [], ->
and ().
The following operator cannot be overloaded: the dot operator (.), the scope
resolution operator (::), sizeof, ?: and .*.
An overloaded operator cannot have default arguments.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Operator Overloading in C++: Implementing the Money Class with +, ==, <, and << Operators and more Lecture notes C programming in PDF only on Docsity!

OPERATOR OVERLOADING

Fundamentals

 There are many operators available that work on built-in types,

like int and double.

 Operator overloading -- is the creation of new versions of these operators for

use with user-defined types.

 Operators usually refer to C++ predefined operators:

o arithmetic operators: +, - , *, /, %

o relational operators: <, <=, ==, !=, >, >=

o assignment operator: =

o logical operators: &&, || ,!

o input/output operators: <<, >>

 It is not as difficult as it sounds. Some things to note:

o An operator in C++ is just a function that is called with special

notation (usually more intuitive or familiar notation). Overloading an

operator simply involves writing a function.

o C++ already does some operator overloading implicitly on built-in

types. Consider the fact that the + operator already works for ints,

floats, doubles, and chars. There is really a different version of the +

operator for each type.

Operator overloading is done for the purpose of using familiar operator notation

on programmer-defined types (classes).

Some rules regarding operator overloading

 Overloading an operator cannot change its precedence.

 Overloading an operator cannot change its associativity.

 Overloading an operator cannot change its "arity" (i.e. number of operands)

You cannot change the number of arguments that an operator takes.

 It is not possible to create new operators -- only new versions of existing

ones.

 Operator meaning on the built-in types cannot be changed.

 The following operator can only be overloaded as member functions: =, [], - >

and ().

 The following operator cannot be overloaded: the dot operator (.), the scope

resolution operator (::), sizeof, ?: and .*.

 An overloaded operator cannot have default arguments.

Format

 An operator is just a function. This means that it must be created with a return

type, a name, and a parameter list

 The rules above give some restrictions on the parameter list

 The name of an operator is always a conjunction of the keyword operator and

the operator symbol itself. Examples:

o operator+ o operator++ o operator<< o operator==

 So the format of an operator overload declaration is just like that of a

function, with the keyword operator as part of the name:

returnType operator OperatorSymbol ( parameterList );

Overloading operator implementation

 Operations for C++ primitive data types (such as int , char and double ) are

predefined in C++ language.

int main() { int x, y = 3; x = y + 10; // OK (int + int), other arithmetic operators - , *, /, % // also OK (int = int) -- assignment if (x < y) // OK (int < int), other logical operators <=, >, >=, ==, != ...

 But, for user-defined data types (Classes), C++ doesn't have definitions for

those operators.

class Money { public: Money(); Money(int d, int c); Money(int allc); double getAmount(); // Returns the amount as a double void printMoney(); // prints a money to cout, in the form $xx.yy private: int dollar; int cent; }; int main() { Money m1(3, 25), m2(19, 5);

Example

// filename: money.h -- Header file for class Money

#ifndef MONEY_H #define MONEY_H #include using namespace std; class Money { public: Money() : dollar(0), cent(0) {} Money(int d, int c) : dollar(d), cent(c) {} Money(int allc); Money operator+(const Money & mo2) const; Money operator-(const Money & mo2) const; // binary - Money operator-() const; // unary - bool operator==(const Money & mo2) const; bool operator<=(const Money & mo2) const; int getDollars() const { return dollar; } int getCents() const { return cent; } // friend functions friend ostream& operator<<(ostream& out, const Money & m); friend istream& operator>>(istream& in, Money & m); friend bool operator>(const Money &, const Money &); private: int dollar; int cent; }; // prototypes of overloaded operators implemented as // regular functions bool operator<(const Money &, const Money &); bool operator!=(const Money &, const Money &); #endif


// filename: money.cpp -- Implementation file for class Money

#include "money.h" Money::Money(int allc) { dollar = allc / 100; cent = allc % 100; } Money Money::operator+(const Money & m2) const

int total = (dollar * 100 + cent) + (m2.dollar * 100 + m2.cent); Money local(total); return local; } Money Money::operator-(const Money & m2) const // this - mo { int diff = (dollar * 100 + cent) - (m2.dollar * 100 + m2.cent); Money local(diff); return local; } Money Money::operator-() const // unary - { int neg = - (dollar * 100 + cent); Money local(neg); return local; } bool Money::operator==(const Money & m2) const { int thistotal = (dollar * 100 + cent); int m2total = (m2.dollar * 100 + m2.cent); return (thistotal == m2total); } bool Money::operator<=(const Money & m2) const { int thistotal = (dollar * 100 + cent); int m2total = (m2.dollar * 100 + m2.cent); return (thistotal <= m2total); / if (*this < m2 || *this == m2) return true; else return false; */ } // no keyword "friend" in the function definition ostream& operator<<(ostream& out, const Money & m) { out << "$" << m.dollar // dollar private in m -- OK << "." << m.cent; // cent private in m -- OK return out; } istream& operator>>(istream& in, Money & m) { char dollarSign; double moneyAsDouble;

if (m1 > m2) cout << "Greaterthan.\n"; else cout << "NOT Greaterthan.\n"; bool ans = m1 > m2; cout << ans << endl; // prints 0 (false) or 1 (true) system("pause"); return 0; } Run time ouput $2.98 + $15.2 = $18. Not equals. NOT Greaterthan. 0

Top-level (Nonmember) function

 Another way to overload operators is by regular, non-member functions.

 Since the operator is NOT a class method, all operands involved in the

operator become the parameters:

o Binary operators have 2 parameters , the second operand to the

operator. The first operand is the object in which the overloaded

operator is called/invoked.

o Unary operators have 1 parameter.

 Also the operator cannot access private members in the parameter objects.

class Money { public: Money(); Money(int d, int c); Money(int allc); int getDollars() const; int getCents() const; ... // note: NO method for operator< private: int dollar; int cent; }; // Definition of regular, non-member functions. // mo1 < mo bool operator<(const Money & m1, const Money & m2) // note: 2 arguments and NO Money::

int thistotal = m1.getDollars() * 100 + m1.getCents(); int m2total = m2.getDollars() * 100 + m2.getCents(); return (thistotal < m2total); }

Friend function

 Yet another way is to use friend function. Friend functions are declared

within a class, but they are NOT class methods.

 A friend function is actually a regular function which has a privilege to access

private members in the parameter objects.

class Money { public: Money(); Money(int d, int c); Money(int allc); Money operator+(const Money & mo2) const; ... // friend functions friend ostream& operator<<(ostream& out, const Money & m); // to be able to do cout << obj friend istream& operator>>(istream& in, Money & m); // to be able to do cint >> obj private: int dollar; int cent; }; // no keyword "friend" in the function definition ostream& operator<<(ostream& out, const Money & m) { out << "$" << m.dollar // dollar private in m -- OK << "." << m.cent ; // cent private in m -- OK return out; } istream& operator>>(istream& out, Money & m) { char dollarsign; double moneyAsDouble; in >> dollarSign; // first eat up '$' in >> moneyAsDouble; // xx.yy m.dollar = static_cast(moneyAsDouble); m.cent = static_cast(moneyAsDouble * 100) % 100; return in; }

Money operator*(double r, const Money & m) { int total = m.toAllCents() * r; Money local(total); return local; }

 Also for the reason above, the operator<< and operator>> are often

implemented as friend functions.

int main() { Money m1(2, 98); cout << m1; }

 Automatic Type Promotion

 If an operator is expecting a class object but received a different type,

if there is a constructor in the class which can convert it to the class,

the conversion/promotion is automatically applied by the compiler.

Example: Suppose the operator+ is implemented as a member function in

Money. Then in the application:

int main() { Money m1(3, 25), m2; m2 = m1 + 6; // 2nd operand is int, not Money. // This int is promoted to a Money object by // the Money constructor which has one int argument // if it is defined (and in our example, it is).

Overloading Other Operators

 Operator[] -- index operator

// A class with an array of five double's. class DoubleArray

public: DoubleArray5(double initvalue); ... double & operator[](int index) const; // index is the parameter private: int ar[5]; }; // NOTE: return by reference(&) double & DoubleArray5operator[](int index) const { if (index <= 0 || index > 5) { cout << "ILLEGAL INDEX.\n"; exit(1); } else return ar[index]; } int main() { DoubleArray5 myarray(0.0); double d = myarray[2]; // myarray.operator myarray[1] = 5.7; // can be used on the LHS of = ... }

 Operator++ and operator -- -- increment/decrement operators

// A counter class class Counter { public: Counter(int c = 0); // initializes 'count' to c ... Counter operator++(); // pre-increment Counter operator++(int i); // post-increment private: int count; }; Counter Counter::operator++() { // First, increment 'count'. count++; // Second, create a local object with the new count. Counter local(count); // Third, return the local object. return local; }

 Type conversion

Conversion Routine in Destination Routine in source
Basic to basic
(float to int)
Built in Built in
Basic to class
(int to obj)
Constructor
Class to Basic
(obj to int)
Operator function
Class to class
(obj to otherObj)
Constructor Operator function
o Example: Class to basic and basic to class
 Metric system vs English system
const float MTF=3.280833;
Class Es
int feet;
int inches;
public:
Es(int f, float i)
feet=f;
inches=i;
//basic to class
Es(float m) //m is a metric value
float fi=MTF *m;
feet=fi;
inches=12*(fi-feet)
//class to basic
operator float()
//In Main
Es e(2,3.0);
float y;
float ff=inches/12;
ff+=feet;
return ff/MTF;
y=e; //class to basic
e=y; //basic to class
o Example: Class to class - Polar to Cartesian
Polar p;
Cartesian c;
p=c;
//or
c=p;
Class Cartesian
double x;
double y;
public:
Cartesian()
{x=0;y=0;}
Cartesian(doubly x, double y)
this.x=x;
this.y=y;
//added constructor
Cartesian(Polar p)
Class Polar
double r=P.getRadius();
double a=p.getAngle();
x=r*cos(a;)
y=r*cos(a);
double radius;
double angle;
public:
Polar()
radius=0;
angle=0;
Polar (double r, double a)
radius=r;
angle=a;