Uploaded by Ayesha Kashif

lecture 15

advertisement
CS112: Object Oriented
Programming
Muhammad Salman Saeed
Operator Arguments
• the ++ operator is applied to a specific object, as in
the expression ++c1
• What does this operator increment?
• It increments the count data in the object of which it
is a member
• Since member functions can always access the
particular object for which they’ve been invoked, this
operator requires no arguments
Operator Return Values
• The operator++() function has a defect. You will
discover it if you use a statement like this in main():
c1 = ++c2;
• The compiler will complain. Why
• Because ++ operator is defined to have a return type
of void in the operator++() function, while in the
assignment statement it is being asked to return a
variable of type Counter
• The normal ++ operator, applied to basic data types
such as int, would not have this problem
int x,y; y=10; x = y ++;
class Counter{
int count;
public:
Counter() : count(0)
{}
int get_count()
{ return count; }
Counter operator ++ (){
++count;
Counter temp;
temp.count = count;
return temp;
}
};
c1
count
2
0
1
c2
count
Counter class Example
main()
{
Counter c1, c2;
cout << “\nc1=” << c1.get_count();
cout << “\nc2=” << c2.get_count();
++c1;
++c1;
c2 = ++c1;
c2 =c1;
cout << “\nc1=” << c1.get_count();
cout << “\nc2=” << c2.get_count() ;
}
Program Output
c1=0
02
c2=0
c1=2
c2=2
Nameless Temporary Objects
Counter temp;
temp.count = count;
return temp;
main()
{
Counter c1, c2;
cout << “\nc1=” << c1.get_count();
cout << “\nc2=” << c2.get_count();
++c1;
c2 = ++c1;
cout << “\nc1=” << c1.get_count();
cout << “\nc2=” << c2.get_count() ;
}
class Counter{
int count;
public:
Counter() : count(0)
{}
Counter(int c) : count(c)
{}
int get_count()
{ return count; }
Counter operator ++ (){
++count;
return Counter(count);
}
};
Postfix Notation
• So far we’ve seen the increment operator used only in its prefix form.
++c1
• What about postfix, where the variable is incremented after its value
is used in the expression?
c1++
class Counter{
private:
int count;
public:
Counter() : count(0)
{}
Counter(int c) : count(c)
{}
int get_count() const
{ return count; }
Counter operator ++ (){
return Counter(++count);
}
Counter operator ++ (int){
return Counter(count++);
}
};
c1
count
02
31
c2
count
main(){
Counter c1, c2;
cout << “c1=” << c1.get_count();
cout << “c2=” << c2.get_count();
++c1; c2 = ++c1;
cout << “c1=” << c1.get_count();
cout << “c2=” << c2.get_count();
c2 = c1++;
cout << “c1=” << c1.get_count();
cout << “c2=” << c2.get_count() ;
}
Program Output
c1=0
20
++c1;
c2++c1;
= c1++;
c2=0
c1=2
c1=3
c2=2
c2=2
Example – Distance class
• Overload pre-increment and pre-decrement unary operator for
distance class such that
•
•
•
•
Increment: add 1 in feet and 1 in inches
Decrement: subtract 1 from feet and 1 from inches
Pre increment – prefix
Post increment – post fix
Overloading Binary Operators
• Binary operator can be overloaded as easy as unary operator by using
a non static function
• Distance objects could be added using a member function add_dist():
dist3.add_dist(dist1, dist2);
• By overloading the + operator we can reduce this dense-looking
expression to
dist3 = dist1 + dist2;
class Distance {
dist1
d2
private:
feet 3
2
feet
int feet;
inches 2.25
inches 1.5
float inches;
dist2
public:
feet 2
Distance() : feet(0), inches(0.0) { }
Distance(int ft, float in) : feet(ft), inches(in) { }
inches 2.25
feet 5
void showdist() const
dist3
inches 3.75
{ cout << feet << “ : ” << inches ; }
feet 5
Distance operator + ( Distance d2) const{
inches 3.75
int f = feet + d2.feet;
Distance dist1(3, 4.5);
float i = inches + d2.inches;
dist4
Distance
dist2(11,
6.25);
if(i >= 12.0) {
feet 10
Distance
dist3;
i -= 12.0; f++;
inches 7.5
dist3
=
dist1
+
dist2;
}
return Distance(f,i);
Distance dist4;
}
dist4 =dist3 + dist1 + dist2;
};
Cont.
• dist3 = dist1 + dist2
• The argument on the left side of the operator (dist1 in this case) is the
object of which the operator is a member
• The object on the right side of the operator (dist2) is as an argument
to the operator + function
• The operator returns a object by value, which is assigned to dist3
Overloaded binary operator: one argument
Cont.
• In the operator+() function, the left operand is accessed directly –
since this is the object of which the operator is a member
• The right operand is accessed as the function’s argument – as d2.feet
and d2.inches
• An overloaded operator always requires one less argument than its
number of operands, since one operand is the object of which the operator is
a member
• That’s why unary operators require no arguments
Concatenating Strings
int main()
{
char str1[12] = "hello";
char str2[ ] = "world";
strcat(str1, str2);
cout << "str1 = " << str1 << endl;
cout << "str2 = " << str2 << endl;
return 0;
}
str1[12]
he l l o
\0
str2[6]
wo r l d
\0
str1[12]
h e l l owo r l d
\0
Program Output
str1 = helloworld
str2 = world
• The + operator cannot be used to concatenate C-strings. That is,
you can’t say
str3 = str1 + str2;
• we can overload the + operator to perform such concatenation
class String {
private:
char str[80];
public:
String(){
strcpy(str, “");
}
String( char s[ ] ) {
strcpy(str, s);
}
void display() const {
cout << str;
}
String operator + (String ss) const {
String temp;
if( strlen(str) + strlen(ss.str) < 80 ) {
strcpy(temp.str, str);
strcat(temp.str, ss.str);
}
else
{ cout << “\nString overflow”; exit(1); }
return temp;
}
};
String class
main() {
String s1 = “Hello ”;
//String s1("\Hello ");
String s2 = “world !”;
//String s2(“ world !");
String s3;
s1.display();
s2.display();
s3 = s1 + s2;
s3.display();
}
Program Output
Hello world !
Hello world !
Cont.
String operator + (String ss) const {
String temp;
if( strlen(str) + strlen(ss.str) < 80 ) {
strcpy(temp.str, str);
strcat(temp.str, ss.str);
}
else
{ cout << “\nString overflow”; exit(1); }
return temp;
}
ss world! \0
temp Hello \0
World! \0
String s1 = “Hello ”;
String s2 = “world !”;
String s3;
s3 = s1 + s2;
s1 Hello \0
s2 world !\0
s3 Hello world!\0
Go to program
Overloading -, + and = binary Operators
class ThreeD {
int x, y, z;
public:
ThreeD() { x = y = z = 0; }
ThreeD(int i, int j, int k)
{ x = i; y = j; z = k; }
ThreeD operator+(ThreeD op2);
ThreeD operator=(ThreeD op2);
ThreeD operator-(ThreeD op2);
void show() ;
};
// Overload subtraction.
ThreeD ThreeD::operator-(ThreeD op2) {
ThreeD temp;
temp.x = x - op2.x;
temp.y = y - op2.y;
temp.z = z - op2.z;
return temp;
}
// Overload +.
ThreeD ThreeD::operator+(ThreeD op2) {
ThreeD temp;
temp.x = x + op2.x;
temp.y = y + op2.x;
temp.z = z + op2.z;
return temp;
}
Cont.
// Overload assignment.
ThreeD ThreeD::operator=(ThreeD op2)
{
x = op2.x;
y = op2.y;
z = op2.z;
return *this;
}
void ThreeD::show() {
cout << x << ", ”<< y << ", ”<< z << "\n";
}
PROGRAM OUTPUT:
Original value of a: 1, 2, 3
Original value of b: 10, 10, 10
b - a: 9, 8, 7
main() {
ThreeD a(1, 2, 3), b(10, 10, 10), c;
cout << "Original value of a: ";
a.show();
cout << "Original value of b: ";
b.show();
c = b - a;
cout << “b - a: ";
c.show();
}
Multiple Overloading
• We’ve seen different uses of the + operator: to add distances and to
concatenate strings.
• You could put both these classes together in the same program, and
C++ would still know how to interpret the + operator:
• It selects the correct function to carry out the “addition” based on the
type of operand
• d1 = d2 + d3;
• s1 = s2 + s3;
Comparison Operator <
main() function
Distance dist1(3, 4.5);
Distance dist2(6, 2.5);
if( dist1 < dist2 )
cout << “\ndist1 is less than dist2”;
else
cout << “\ndist1 is greater than (or equal to) dist2”;
bool Distance::operator < (Distance d2) const {
float bf1 = feet + inches/12;
float bf2 = d2.feet + d2.inches/12;
return (bf1 < bf2) ? true : false;
}
Arithmetic assignment: Operator +=
main() function
Distance dist1(3, 2.5);
Distance dist2(5 3.25);
dist1 += dist2;
void Distance::operator += (Distance d2)
{
feet += d2.feet;
inches += d2.inches;
if(inches >= 12.0) {
inches -= 12.0;
feet++;
}
}
The Subscript Operator [ ]
• The subscript operator, [], which is normally used to access array
elements, can be overloaded.
• This is useful, for example if we want to make a “safe” array: One that
automatically checks the index numbers you use to access the array,
to ensure that they are not out of bounds.
• To be useful, the overloaded subscript operator must return by
reference.
Cont.
• To see why this is true, lets see three example
programs that implement a safe array, each one using
a different approach to inserting and reading the
array elements:
• Separate put() and get() functions
• A single access() function using return by reference
• The overloaded [] operator using return by reference
• All programs create a class called safearray,
• only member data is an array of 100 int values,
• and all three check to ensure that all array accesses are
within bounds.
Separate get() and put() Functions
const int LIMIT = 100;
class safearray {
private:
int arr[LIMIT];
public:
void putel(int n, int elvalue) {
if( n< 0 || n>=LIMIT ) {
cout << “\nIndex out of bounds”;
exit(1);
}
arr[n] = elvalue;
}
int getel(int n) const {
if( n< 0 || n>=LIMIT ){
cout << “\nIndex out of bounds”;
exit(1);
}
return arr[n];
}
};
int main() {
int temp;
safearay sa1;
for(int j=0; j<LIMIT; j++)
sa1.putel(j, j*10);
for(j=0; j<LIMIT; j++) {
temp = sa1.getel(j);
cout << “Element “
<< j << “ is “ << temp ;
}
}
Single access() Function Returning by Reference
const int LIMIT = 100;
class safearray {
private:
int arr[LIMIT];
public:
int& access(int n) {
if( n< 0 || n>=LIMIT ) {
cout << “\nIndex out”;
exit(1);
}
return arr[n];
}
main() {
int temp;
safearray sa1;
for(int j=0; j<LIMIT; j++)
sa1.access(j) = j*10;
for(j=0; j<LIMIT; j++) {
temp = sa1.access(j);
cout << “Element “ << j
<< “ is “ << temp ;
}
}
The statement
sa1.access(j) = j*10;
causes the value j*10 to be placed in arr[j], the return value
of the function
Overloaded [] Operator Returning by Reference
main()
const int LIMIT = 100;
{
class safearray {
int temp;
private:
safearray sa1;
int arr[LIMIT];
for(int j=0; j<LIMIT; j++)
public:
sa1[ j ] = j*10;
for(j=0; j<LIMIT; j++) {
int& operator [ ](int n) {
temp = sa1[ j ];
if( n< 0 || n>=LIMIT ) {
cout << “Element “ << j
cout << “\nIndex out of bounds”;
<< “ is “ << temp ;
exit(1);
}
}
}
return arr[n];
}
}
Overloading Restrictions
• Can not overload the operators as they apply to builit-in
data types.
Example: y = 5;
x = y + 5; // overloading + operator so that x
becomes 15 is illegal.
• Must respect the original "Functional" template of the
operators. You can not convert a unary operator to a
binary operator.
Example: y = x ++ z; //Illegal
• You can not change the operator's precedence.
Example: Can not make the + operator higher
precedence than the * operator.
Not All Operators Can Be Overloaded
• The following operators cannot be overloaded
•
•
•
•
•
member access or dot operator (.)
scope resolution operator (::)
the conditional operator (?:)
pointer-to-member operator (->)
can’t create new operators (like *&) and try to overload them
• only existing operators can be overloaded.
Data Conversion
• The = operator will assign a value from one variable to
another, instatements like
intvar1 = intvar2;
where intvar1 and intvar2 are integer variables
• Also, = assigns the value of one user-defined object to
another, provided they are of the same type, in
statements like
dist3 = dist1 + dist2;
where the result of the addition, is assigned to another object
of type Distance, dist3.
• dist4 = dist3;
Cont.
• Thus, assignments between types, whether they are
basic types or user-defined types, are handled by the
compiler with no effort on our part, provided that the
same data type is used on both sides of the equal sign
• what happens when the variables on different sides
of the = are of different types?
• For example:
• dist2 = 7.55;
Distance class
class Distance {
private:
int feet;
float inches;
public:
Distance() : feet(0), inches(0.0)
{}
Distance(int ft, float in) : feet(ft), inches(in)
{}
void getdist() {
cout << “\nEnter feet: “; cin >> feet;
cout << “Enter inches: “; cin >> inches;
}
void showdist() const {
cout << feet << “ : ” << inches ;
}
};
Conversions Between Objects and Basic Types
main() {
Distance(float meters) {
float mtrs;
float fltfeet = 3.280833 * meters;
Distance dist1 = 2.35;
feet = int(fltfeet);
cout << “dist1=“;
inches = 12*(fltfeet-feet);
dist1.showdist();
}
mtrs = dist1;
operator float() const {
cout << “\ndist1 = “ << mtrs << “
float fracfeet = inches/12;
meters\n”;
fracfeet += feet;
Distance dist2(5, 10.25);
return fracfeet/3.280833;
mtrs = dist2;
}
cout << “\ndist2 = “ << mtrs << “
PROGRAM OUTOUT
meters\n”;
dist1 = 7 : 8.51949
}
dist1 = 2.35 meters
dist2 = 1.78435 meters
Conversions Between Objects of Different
Classes
• Can be done using
• one-argument constructor
• conversion function
• The choice depends upon whether the conversion
routine has to be declared in the source class or in the
destination class
• To illustrate, consider a program that contains two
classes: A and B. Also consider the statement:
object_A = object_B;
Cont.
• In the above statement, object_B of type B is converted
to type A and assigned toobject_A.
• object_B is the source and object_A is the destination.
• If class B handles the conversion, it will hold a
conversion function.
• On the other hand, if class A carries out the conversion,
it will do that through a constructor that takes an
argument of type class B.
Example program 01: km to miles
class Kilometers{
private:
double kms;
public:
Kilometers(double k) :
kms(k)
{ }
void display() {
cout<<kms;
}
double getValue() {
return kms;
}
};
class Miles {
private:
double miles;
public:
Miles(double m) : miles(m)
{ }
Miles(Kilometers KM) {
miles = KM.getValue()/1.61;
}
void display() {
cout <<“ miles = “<< miles;
}
operator Kilometers() {
return Kilometers(miles*1.61);
}
};
Cont.
main( ) {
// Converting using the conversion function
Miles m1 = 100;
Kilometers k1 = m1;
m1.display();
cout << " = "; k1.display();
cout << endl;
}
// Converting using the constructor
Kilometers k2 = 100;
Miles m2 = k2;
k2.display();
cout << " = "; m2.display();
cout << endl;
Output
100 miles = 160.934 kilometeres
100 kilometers = 62.1371 miles
• Any Questions
Contact information:
Engr. Muhammad Salman Saeed
Academic Block 3rd Floor, CS-19
salman.saeed@giki.edu.pk
Download