Presentation is loading. Please wait.

Presentation is loading. Please wait.

CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element.

Similar presentations


Presentation on theme: "CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element."— Presentation transcript:

1 CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element stored in a vector using the indexing operator [] rather than the at() member function: IntVector myVector( 4 ); myVector[2] = 34; cout << myVector[2] << endl; We will see how to add this to the IntVector class we need to overload the indexing operator [] we will first examine operator overloading for the simpler Complex class then we will return to the IntVector class.

2 CPSC 252 Operator Overloading and Convert Constructors Page 2 The complex number class Complex numbers have the form: a + ib where a and b are real numbers and i is such that i 2 = -1 Suppose that z 1 =a+ib and that z 2 =c+id then: z 1 + z 2 = (a + c) + i (b + d) z 1 – z 2 = (a – c) + i (b – d) z 1 * z 2 = (ac – bd ) + i (ad + bc) z 1 / z 2 = ( (ac + bd) + i (bc – ad) ) / (c 2 + d 2 ) Let us now consider a declaration of the Complex class

3 CPSC 252 Operator Overloading and Convert Constructors Page 3 class Complex { public:// not yet complete Complex( void ); //Post: complex number is 0 + 0*i Complex( double real, double imag ); //Post: complex number is real + imag*i void setComplex( double real, double imag ); //Post: complex number is real + imag*i double getReal( void ) const; //Post: real part has been returned double getImag( void ) const; //Post: imaginary part has been returned private: double realPart; double imagPart; };

4 CPSC 252 Operator Overloading and Convert Constructors Page 4 Implementing complex arithmetic in C++ the basic member functions are easy a complete version is on the course website we will focus on adding overloaded operators A client can perform operations such as: Complex num( 5, 4 ); cout << “Real part:” << num.getReal() << “Imaginary part:” << num.getImag() << endl; But code such as the following will not compile: Complex num1( 5, 4), num2( 6, 4), num3; num3 = num1 + num2; Reason: the “ +” operator is not been defined when the left and right operands are of type Complex

5 CPSC 252 Operator Overloading and Convert Constructors Page 5 Overloading operators in C++ We can define how to add two objects of type Complex Any binary operator can be: overloaded as a member function of a C++ class the left operand must be an instance of that class Let’s recall our client code: num3 = num1 + num2; the left operand is of type Complex so we can define an overloaded + operator the alternate syntax for invoking operators is num3 = num1.operator+( num2 );

6 CPSC 252 Operator Overloading and Convert Constructors Page 6 Overloaded addition operator Declaration of + operator (header file / class declaration): Complex operator+( const Complex& rComplex ) const; Implementation (source file / class definition): Complex Complex::operator+( const Complex& rComplex ) const { Complex sum; sum.realPart = realPart + rComplex.realPart; sum.imagPart = imagPart + rComplex.imagPart; return sum; }

7 CPSC 252 Operator Overloading and Convert Constructors Page 7 Other overloaded operators in Complex The binary arithmetic operators can all be overloaded: subtraction: operator– multiplication: operator* division: operator/ What about the assignment operator? no need to define operator= the compiler-provided default works just fine component-wise assignment is what we want for Complex Are there others operators we need to overload?

8 CPSC 252 Operator Overloading and Convert Constructors Page 8 Overloaded the “strictly less than” operator One complex numbers less than another iff both parts are strictly less than the other’s parts Declaration of < operator (header file / class declaration): bool operator<( const Complex& rComplex ) const; Implementation (source file / class definition): bool Complex::operator<( const Complex& rComplex ) const { return ( realPart < rComplex.realPart ) && ( imagPart < rComplex.imagPart ); }

9 CPSC 252 Operator Overloading and Convert Constructors Page 9 Input and output operators Consider the following client code: Complex num1, num2, num3; cout > num1 >> num2; num3 = num1 + num2; cout << “First num + Second num =“ << num3 << endl; the compiler now has no problem adding num1 and num2 but it does not know how to extract a complex number from an input stream and it doesn’t know how to insert one into an output stream We must provide overloaded “ >” operators

10 CPSC 252 Operator Overloading and Convert Constructors Page 10 Stream (I/O) variables the variable cin is an instance of a class named istream the variable cout is an instance of a class named ostream they are declared in the library header Consider the following client code: Complex num( 3, 4 ); cout << num << endl; the << operator is left associative it returns the left operand when it is evaluated (just like “ =” ) the expression above is evaluated as: ( ( cout << num ) << endl ) ;

11 CPSC 252 Operator Overloading and Convert Constructors Page 11 Overloading the << operator for the Complex class the left operand is an instance of the ostream class it is not an instance of the Complex class. so the << operator cannot be overloaded in Complex We therefore must declare the << operator as a friend friend ostream& operator<<( ostream& outStream, const Complex& number ); the friend declaration appears within the class declaration a friend of a class is not a member function of the class however, it can access the private members of the class it cannot change the private members because of the const

12 CPSC 252 Operator Overloading and Convert Constructors Page 12 Implementing the << operator for the Complex class ostream& operator<<( ostream& outStream, const Complex& number ) // Non-member function // Uses cout and << from iostream library // Uses fabs() from cmath library // Pre: outStream is a valid ostream // Post: number is output to the given ostream in // the form [realPart] +/- [imagPart]i { outStream << number.realPart << ( number.imagPart < 0 ? "-" : "+" ) << fabs( number.imagPart ) << "i"; return outStream; } C++ “math” absolute value function

13 CPSC 252 Operator Overloading and Convert Constructors Page 13 Overloading the >> operator for the Complex class the left operand is an instance of the istream class it is not an instance of the Complex class. so we (again) declare the >> operator as a friend friend istream& operator>>( istream& inStream, const Complex& number ); Consider the following client code: Complex num1, num2; cin >> num1 >> num2; the >> operator is (again) left associative and it returns its left operand ( ( cin >> num1 ) >> num2 );

14 CPSC 252 Operator Overloading and Convert Constructors Page 14 Implementing the >> operator for the Complex class istream& operator>>( istream& inStream, Complex& number ) // Non-member friend function // Uses cin and >> from iostream library // Pre: inStream is a valid istream // Post: number has been read from the keyboard with // format: [realPart]+/-[imagPart]i with no spaces { char iChar; // used to read 'i’, which is ignored inStream >> number.realPart >> number.imagPart >> iChar ; return inStream; }

15 CPSC 252 Operator Overloading and Convert Constructors Page 15 A caution about declaring “friend” methods Declaring a function to be a friend violating the principle of encapsulation a function external to the class can access private data a function external to the class can change private data a function external to the class can invoke private methods normally we do not want to allow this sometimes we have to do this, as for > only do this when it is absolutely necessary we can declare a non-friend function calling public methods istream& operator>>( istream& inStream, const Complex& number );

16 CPSC 252 Operator Overloading and Convert Constructors Page 16 Non-friend << operator for the Complex class ostream& operator<<( ostream& outStream, const Complex& number ) // Non-member non-friend function // Uses cout and << from iostream library // Uses fabs() from cmath library // Pre: outStream is a valid ostream // Post: number is output to the given ostream in // the form [realPart] +/- [imagPart]i { outStream << number.getReal() << ( number.getImag() < 0 ? "-" : "+" ) << fabs( number.getImag() ) << "i"; return outStream; } Less efficient because of method calls, but not too ineffcient

17 CPSC 252 Operator Overloading and Convert Constructors Page 17 Operator precedence In C++ operators are applied in order of their precedence { outStream << number.getReal() << ( number.getImag() < 0 ? "-" : "+" ) << fabs( number.getImag() ) << "i"; return outStream; } Parentheses are required for this expression because of precedence in this example C++ conditional operator: boolean ? expression : expression

18 CPSC 252 Operator Overloading and Convert Constructors Page 18 Overloading other operators (mixing types) Now consider the following client code that will not compile: Complex num1( 4.5, 5.0), num2; double value = 5.5; num2 = num1 + value; the overloaded + operator only works when both operands are of type Complex but here the right operand is of type double. We can now proceed in two ways: supply another overloaded + operator that takes a left operand of type Complex and a right operand of type double supply a convert constructor that converts a double to an object of type Complex

19 CPSC 252 Operator Overloading and Convert Constructors Page 19 Option 1: Supply another overloaded + operator Complex Complex::operator+( const double& right ) const // Member operator function // Post: the sum of this Complex and the double right is returned { Complex sum; sum.realPart = realPart + right; sum.imagPart = imagPart; return sum; }

20 CPSC 252 Operator Overloading and Convert Constructors Page 20 Option 2: Supply a convert constructor Declaration in the header file: Complex( double num ); //Post: complex number is num + 0i Implementation in the source file: Complex::Complex( double num ) //Post: complex number is num + 0i { realPart = num; imagPart = 0.0; } can be called explicitly in client code can also be called implicitly by the compiler as needed

21 CPSC 252 Operator Overloading and Convert Constructors Page 21 Explicit conversion The programmer specifies use of a conversion constructor Complex num1( 4.5, 5.0), num2; double value = 5.5; num2 = num1 + Complex( value ); This is an example of type casting (or type conversion) double num = 6.785; int rounded = int( num + 0.5 ); or char alpha = ‘A’; cout << int( alpha ) << endl;

22 CPSC 252 Operator Overloading and Convert Constructors Page 22 Implicit conversion The compiler decides to use a conversion constructor void myFunc( Complex param ) { } double value = 5.5; myFunc( value ); The convert constructor is called implicitly to convert value to a Complex when it is passed as a parameter to myFunc

23 CPSC 252 Operator Overloading and Convert Constructors Page 23 Which is best: Option 1 or Option 2? Advantages for Option 1: no implicit conversion the more explicit our code is, the easier it is to debug Disadvantage for Option 1: we may have to overload other versions of the + operator Complex operator+( double num, const Complex& rComplex); //Post: the sum of (num + 0i) and rComplex is //returned double num = 6.5; Complex complex1( 5.5, 3.5 ), complex2; complex2 = num + complex1; Left operand is double and right operand is Complex

24 CPSC 252 Operator Overloading and Convert Constructors Page 24 Advantages for Option 2 a single constructor that converts a double to Complex one version of the overloaded + operator we can perform addition on many combinations of operands double num = 6.5; Complex complex1( 5.5, 3.5 ), complex2( 0.5, 1.5 ), complex3; complex3 = complex1 + complex2; complex3 = Complex( num ) + complex2; complex3 = complex1 + Complex( num ); Disadvantage: objects can be implicitly converted by the compiler this can sometimes lead to code that is difficult to debug

25 CPSC 252 Operator Overloading and Convert Constructors Page 25 The explicit keyword The disadvantage of Option 2 can be removed by using the explicit keyword add this keyword to the declaration of the constructor this prevents the compiler from implicitly converting so a double will not become a Complex only explicit invocations of the convert constructor are allowed public: explicit Complex( double value );

26 CPSC 252 Operator Overloading and Convert Constructors Page 26 Operator overloading – the indexing operator We now (finally) overload the indexing operator [] for our IntVector class. For the same reason that we have two versions of the at() member function, we need to declare two versions of the overloaded indexing operator: Accessor: int operator[]( int index ) const; // Post: if 0 <= index < size() the element at // index is returned, otherwise program aborted Mutator: int& operator[]( int index ); // Post: if 0 <= index < size() the element at // index is returned, otherwise program aborted

27 CPSC 252 Operator Overloading and Convert Constructors Page 27 Implementing the overloading indexing operator The implementation is exactly the same as the corresponding at() functions simply call the at() function in the operator[] function int IntVector::operator[]( int index ) const { return at( index ); } this is concise but it is a little inefficient because of the function call this operator may be called many times by a client duplicating the code in at() is more efficient but code is “bloated” if we have blocks of duplicate code

28 CPSC 252 Operator Overloading and Convert Constructors Page 28 The inline keyword We can actually have the best of both approaches the concise version of the operator[] no overhead for a function call to at( inline int at( int index ) const { return value[ index ]; } The inline keyword suggests that: the compiler should replace each call to the inline function with the body of that function the compiler should avoid the function call the compiler can ignore the inline keyword if it sees fit!


Download ppt "CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element."

Similar presentations


Ads by Google