1 / 110

Topics on Ad Hoc Polymorphism

Topics on Ad Hoc Polymorphism. Class-Defined Conversions Overloading and Function Selection Friend Functions Unary Operator Overloading Binary Operator Overloading Overloading Assignment & Subscript Operators Overloading Operator () for Indexing Overloading new and delete

baylee
Télécharger la présentation

Topics on Ad Hoc Polymorphism

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Topics on Ad Hoc Polymorphism • Class-Defined Conversions • Overloading and Function Selection • Friend Functions • Unary Operator Overloading • Binary Operator Overloading • Overloading Assignment & Subscript Operators • Overloading Operator () for Indexing • Overloading new and delete • More Signature-Matching • Polynomial:Type And Language Expectations

  2. Go get me a ball General Polymorphism • Polymorphism is a means of giving different meanings to the same message • The meanings are dependent on the type of data being processed

  3. Type Conversions • Conversion is the explicit or implicit change of value between types • Conversions provide a form of polymorphism Float Int

  4. Ad Hoc Polymorphism • Overloading functions gives the same function name different meanings: ad hoc polymorphism • Name has different interpretations that depend on function selection based on signature-matching algorithm for C++ • print (the int) 3 • print (the matrix) 2.2 3.3 5.1 9.3 • 71.3 6.0 9.9 12.55 • print (the shape)

  5. Overloading and OOP • The LOOK and FEEL principle of OOP is that user-defined types must enjoy the same privileges as native types • Client expects convenience without regard to native/nonnative distinction • Supplier needs to achieve ease of use for ADTs • Native types in the kernel language can be mixed in expressions because it is convenient and would otherwise be burdensome to designate conventionally expected conversions

  6. New Cast Notation • A functional notation is equivalent to a cast • type-name (expression) • The type must be expressible as an identifier

  7. Equivalent Expressions and Casting • x = float(i); //C++ functional notation • x = (float) i; //equivalent to above • p = (int*) q; //legal cast • p = int*(q); //illegal • typedef int* int_ptr; //equivalent • p = int_ptr(q); • Functional notation is the preferred style

  8. Class-defined Conversions • Explicit type conversion of an expression is necessary when either the implicit conversion is not desired or the expression is not legal otherwise • To achieve the integration of ADTs and native types there are two mechanisms for having a member function provide an explicit conversion • conversion constructors class-name::operator type ( ) • complex::complex(double) complex::operator double() • double complex complex double

  9. Constructors and Type Conversion • A constructor of one argument is de facto a type conversion from the argument's type to the constructor's class type • string::string(const char* p) • { len = strlen(p); • s = new char[len + 1]; • strcpy(s, p); } • This is automatically a type transfer from char* to string and it is available both explicitly and implicitly

  10. The Conversion Operator • General form for conversion member function • operator type() { . . . } • A conversion function must be a non-static member function without a return type and with an empty argument list • These conversions occur implicitly • in assignment expressions • in arguments to functions • in values returned from functions

  11. Conversion Operator to Native char* • string::operator char*() • { • char* q = new char[len + 1]; • strcpy(q, s); • return (q); • } • This defines a special conversion function inside the string class to convert from a string to the native type char * • This form doesn't provide access to the underlying string

  12. Explicit & Implicit String Conversions • string s; • char* logo = "Geometrics Inc"; • //perform explicit conversion then assignment • s = string(logo); • //implicit invocation of conversion • s = logo; • These are conversions from an already defined type to a user-defined type • It is not possible for the user to add a constructor to a native type such as int or double

  13. Ambiguity and Conversions • A conversion member function of the form A::operator B() and a constructor of the formB::B(const A&) both provide conversions from type A objects to type B objects • Having both can result in ambiguity errors A B A B

  14. Overloading print() print(int) print(int, int) print(foo_bar)

  15. Overloaded Functions in C++ • Overloaded functions are an important in C++ • The overloaded meaning is selected by matching the argument list of the function call to the argument list of the function declaration • When an overloaded function is invoked, the compiler must have a selection algorithm with which to pick the appropriate function • The algorithm that accomplishes this depends on what type conversions are available

  16. Function Overload Selection Algorithm 1. Use an exact match if found 2. Try standard type promotions 3. Try standard type conversions 4. Try user-defined conversions 5. Use a match to ellipsis if found

  17. Best Match and Ambiguities • A best match must be unique and it must be best on at least one argument and as good on all other arguments as any other match • Ambiguity of more than 1 possible match is illegal • Default arguments can lead to ambiguities

  18. Function Selection Algorithm In Use Declarations • int i; • double w; • complex z; • char c, *p; • void f(int); f(i); exact match f(c); standard promotion f(w); standard conversion f(z); user-defined promotion f(p); illegal

  19. Function Overloading (1 of 5) • // Title: greater • #include <iostream.h> • #include <math.h> //for sqrt • class complex { • public: • complex(double r): real(r), imag(0.0) { } • void assign(double r, double i) • {real = r; imag = i; } • void print() • {cout<< real<< " + "<< imag << "i ";} • operator double() • {return (sqrt(real*real+imag*imag));} • private: • double real, imag; • };

  20. Function Overloading (2 of 5) • inline int greater(int i, int j) • { return ( i > j ? i : j); } • inline double greater(double x, double y) • { return ( x > y ? x : y); } • inline complex greater(complex w,complex z) • { return ( w > z ? w : z); }

  21. Function Overloading (3 of 5) • main() • { • int i = 10, j = 5; • float x = 7.0; • double y = 14.5; • complex w(0), z(0), zmax(0); • w.assign(x, y); • z.assign(i, j); • cout << "compare " << i << " and " << j • << " greater is " • << greater(i, j) << endl; • cout << "compare " << x << " and " << y • << " greater is " • << greater(x, y) << endl; • cout << "compare " << y << " and " ;

  22. Function Overloading (4 of 5) • z.print(); • cout << " greater is " • << greater(y, double(z)) << endl; • zmax = greater(w, z); • cout << "compare "; • w.print(); • cout << " and "; • z.print(); • cout << " greater is "; • zmax.print(); • cout << endl; • }

  23. Function Overloading (5 of 5) • The output from this program is • compare 10 and 5 greater is 10 • compare 7 and 14.5 greater is 14.5 • compare 14.5 and 10 + 5i greater is 14.5 • compare 7 + 14.5i and 10 + 5i greater is 7 + 14.5i

  24. Comments on the greater Program • Three distinct functions are overloaded • The most interesting has complex type for its argument list variables and its return type • The conversion member function operator double is required to evaluate w > z • The complex variables w and z are converted to double • Silently what happens is • double(w) > double(z) ? w : z;

  25. Friend Functions • The keyword friend is a function specifier which gives a nonmember function access to the hidden members of the class • Its use is a method of escaping the data-hiding restrictions of C++ • There must be a good reason for escaping these restrictions as they are important to reliable programming

  26. Show membership card to get in Letting Non-members in I’m a friend, so let me in without a membership card, please. OK, come in.

  27. Reasons for Using Friend Functions • Friend access follows certain understood situations that would othrwise be inconvenient • Operator overloading of binary operators • Some functions need access where the first argument is not properly a class or is a class argument whose source cannot be modified with additional members • Overriding efficiency concerns • Special relationship between classes

  28. Using Friend Functions • A friend function declaration must appear inside the class declaration to which it is a friend • The function is prefaced by the keyword friend and can appear in private or public part • A member function of one class can be a friend function of another class • The member function is declared in the friend's class using the scope resolution operator • If all member functions of one class are friend functions of a second class, then use friend classclass-name

  29. Access via friends • class foo_bar { • friend ostream& operator<< (ostream &, foobar &); • . . . • }; • Because << is tied to ostream class it is not readily modifiable there • As a consequence we need operator << to be either a friend or an ordinary function • The relationship to I/O frequently needs appropriate and efficient access to state

  30. Assignment Compatible Conversion • class complex { • . . . • friend complex operator+(complex, complex); • . . . • }; • 1 + w; //with member function this fails • w + 1; //this is OK either way • Symmetry of application of assignment compatible conversion rules for arguments is desirable

  31. Separating Components into Classes • class tree; • class node { • . . . • friend class tree; • . . . • }; • A special relationship holds between whole and part thatfavors separating thesecomponents

  32. Sub-component Access • friend vect mpy(const vect&, const matrix&); • Need efficient sub-component access to implement a basic operation • More generally, classes must interact intimately

  33. Using Friends • Multiply vector by matrix could be written efficiently if it had access to both classes • It would be a friend function of both classes • Safe access is provided with member functions vect::element() and matrix::element() • We could write a function using this access that would multiply without requiring friend status, but the price in functional call overhead and array bounds checking would make such a matrix multiply unnecessarily inefficient

  34. Using Friends (1 of 3) • // Title: matrix_v • class matrix; //forward reference • class vect { • public: • friend vect mpy(const vect& v, const matrix& m); • . . . • private: • int* p; • int size; • };

  35. Using Friends (2 of 3) • class matrix { //stores integer elements • public: • friend vect mpy(const vect& v, const matrix& m); • . . . • private: • int** base; • int row_size, column_size; • };

  36. Using Friends (3 of 3) • vect mpy(const vect& v, const matrix& m) • { • if (v.size != m.row_size) { //incorrect sizes • cerr << "multiply failed—sizes bad" • << v.size << " & " << m.row_size; • exit(1); • } • vect ans(m.column_size); //use privileged • int i, j; //access to p • for (i = 0; i <= m.ub2(); ++i) { • ans.p[i] = 0; • for (j = 0; j <= m.ub1(); ++j) • ans.p[i] += v.p[j] * m.base[j][i]; • } • return (ans); • }

  37. Controversy of Using Friend Functions • A neat, orderly design principle is that only member functions should have access to the hidden implementation of the ADT • The friend function straddles this boundary since it has access to private members but is not itself a member function • The friend function can be used to provide quick fixes to code that needs access to the implementation details of a class • The mechanism can be abused easily

  38. 38

  39. Operator Overloading (1 of 2) 39

  40. 40 40

  41. 41 41

  42. Unary Operator Overloading • Overload unary operators, such as !, ++, ~, and [] • For this purpose we develop the class clock, which can be used to store time as days, hours, minutes, and seconds

  43. 43 43

  44. 44

  45. 45 45

  46. 46 46

  47. 47 47

  48. 48 48

  49. 49

  50. Comments on the clock Program • The constructor performs the usual conversions from tot_secs to days, hours, minutes, and seconds and acts as a conversion function that properly updates the time • The member function tick constructs clock temp, which adds one second to the total time

More Related