Topics on ad hoc polymorphism l.jpg
This presentation is the property of its rightful owner.
Sponsored Links
1 / 110

Topics on Ad Hoc Polymorphism PowerPoint PPT Presentation


  • 70 Views
  • Uploaded on
  • Presentation posted in: General

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

Download Presentation

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Topics on ad hoc polymorphism l.jpg

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


General polymorphism l.jpg

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


Type conversions l.jpg

Type Conversions

  • Conversion is the explicit or implicit change of value between types

    • Conversions provide a form of polymorphism

      Float Int


Ad hoc polymorphism l.jpg

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)


Overloading and oop l.jpg

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


New cast notation l.jpg

New Cast Notation

  • A functional notation is equivalent to a cast

    • type-name (expression)

  • The type must be expressible as an identifier


Equivalent expressions and casting l.jpg

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


Class defined conversions l.jpg

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


Constructors and type conversion l.jpg

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


  • The conversion operator l.jpg

    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


  • Conversion operator to native char l.jpg

    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


    Explicit implicit string conversions l.jpg

    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


    Ambiguity and conversions l.jpg

    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


    Overloading print l.jpg

    Overloading print()

    print(int)

    print(int, int)

    print(foo_bar)


    Overloaded functions in c l.jpg

    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


    Function overload selection algorithm l.jpg

    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


    Best match and ambiguities l.jpg

    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


    Function selection algorithm in use l.jpg

    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


    Function overloading 1 of 5 l.jpg

    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;

    • };


    Function overloading 2 of 5 l.jpg

    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); }


    Function overloading 3 of 5 l.jpg

    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 " ;


    Function overloading 4 of 5 l.jpg

    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;

    • }


    Function overloading 5 of 5 l.jpg

    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


  • Comments on the greater program l.jpg

    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;


  • Friend functions l.jpg

    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


    Letting non members in l.jpg

    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.


    Reasons for using friend functions l.jpg

    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


    Using friend functions l.jpg

    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


    Access via friends l.jpg

    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


    Assignment compatible conversion l.jpg

    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


    Separating components into classes l.jpg

    Separating Components into Classes

    • class tree;

    • class node {

    • . . .

    • friend class tree;

    • . . .

    • };

      • A special relationship holds between whole and part thatfavors separating thesecomponents


    Sub component access l.jpg

    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


    Using friends l.jpg

    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


    Using friends 1 of 3 l.jpg

    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;

    • };


    Using friends 2 of 3 l.jpg

    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;

    • };


    Using friends 3 of 3 l.jpg

    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);

    • }


    Controversy of using friend functions l.jpg

    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


    Slide38 l.jpg

    38


    Operator overloading 1 of 2 l.jpg

    Operator Overloading (1 of 2)

    39


    Slide40 l.jpg

    40

    40


    Slide41 l.jpg

    41

    41


    Unary operator overloading l.jpg

    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


    Slide43 l.jpg

    43

    43


    Slide44 l.jpg

    44


    Slide45 l.jpg

    45

    45


    Slide46 l.jpg

    46

    46


    Slide47 l.jpg

    47

    47


    Slide48 l.jpg

    48

    48


    Slide49 l.jpg

    49


    Slide50 l.jpg

    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


    Unary operator overloading for clock l.jpg

    Unary Operator Overloading for Clock

    • clock operator++() { tick(); return (*this); }

      • This class overloads the prefix increment operator which updates the implicit clock variable and returns the updated value

      • The overloaded operator is a member function and can be invoked on its implicit single argument


    Member v non member overloading l.jpg

    Member v. Non-Member Overloading

    • Overload prefix ++ using a friend function with call-by-reference:

  • clock operator++(clock& cl)

  • { cl.tick(); return (cl); }

    • The decision to choose between a non-member and a member function typically depends on whether implicit conversion operations are available and desirable

      • Explicit argument passing, as in non-member functions, allows the argument to be automatically coerced


  • Binary operator overloading l.jpg

    Binary Operator Overloading

    • When a binary operator is overloaded using a member function, it has as its first argument the implicitly passed class variable and as its second argument the lone argument list parameter

    • A friend function or an ordinary function has both arguments specified in the parameter list

    • An ordinary function cannot access private members


    Binary addition friend function l.jpg

    Binary Addition Friend Function

    • friend clock operator+(const clock& c1,const clock& c2)

      • Both arguments are candidates for assignment conversions

    • clock operator+(const clock& c1, const clock& c2)

    • {

    • return (c1.tot_secs + c2.tot_secs);

    • }

      • Both arguments are specified explicitly

      • The constructor converts unsigned long int expression into a clock value


    Binary subtraction member function l.jpg

    Binary Subtraction Member Function

    • clock operator-(const clock& c);

      • In the - operation, there is an implicit first argument which takes some getting used to and which can cause asymmetric behavior for binary operators

    • clock clock::operator-(const clock& c)

    • {

    • return (tot_secs - c.tot_secs);

    • }


    Binary multiplication friend function l.jpg

    Binary Multiplication Friend Function

    • The multiplication operation is a binary operation with one argument an unsigned long int and the second argument a clock variable

  • clock operator*(unsigned long int m, const clock& c)

  • {

  • return(m * c.tot_secs);

  • }

    • Implementation forces the multiplication to have a fixed ordering that is type-dependent

    • Common practice to write a second overloaded function to allow either ordering of operands


  • Using the binary clock operations l.jpg

    Using the Binary clock Operations

    • int i = 5;

    • clock c(900), d(800);

    • c + i//legal: i converted to a clock

    • i + c//legal: i converted to a clock

    • c — i//legal: i converted to a clock

    • c.operator—(i)//function call notation

    • i — c//illegal: i is not a clock

    • i.operator—(c)//illegal: function call notation

    • i * c//legal

      • As seen clearly in the use of function call notation, the variable i is not a clock and does not "understand" the meaning of minus


    Lvalues and rvalues l.jpg

    Lvalues and Rvalues

    • A =B

    • c[i]=5 + D[j]


    Overloading assignment subscript l.jpg

    Overloading Assignment & Subscript

    • C++ has reference declarations, and such type modifiers produce lvalues

      • lvalue stands for location value

    • On the right side of an assignment expression, an lvalue is automatically dereferenced

    • On the left side of an assignment expression, an lvalue specifies where a value is to be stored

    • Subscripting uses of these properties of lvalues

    • For ADTs define expressions such as subscript & assignment, unless defaults are satisfactory


    Re implementing the class vect l.jpg

    Re-implementing the Class vect

    • The reimplemented vect class has several improvements to make it safer and more useful

    • A constructor that converts an ordinary integer array to a safe array allows us to develop code using safe arrays and later convert the same code to run efficiently using ordinary arrays

    • The public data member ub is changed to a member function preventing a user from introducing a program error by modifying ub

    • The subscript operator [] is overloaded and replaces the member function element


    Making a safe array l.jpg

    Making a Safe Array

    There isn’t a

    6th one to change!

    Let’s

    change the

    6th vector

    element.

    5

    7

    15


    Safe array with subscripting 1 of 6 l.jpg

    Safe Array with Subscripting (1 of 6)

    • class vect {

    • public:

    • vect();//create a size 10 array

    • vect(int n);//create a size n array

    • vect(const vect& v);//init by vect

    • vect(const int a[], int n); //init by array

    • ~vect() { delete [] p};

    • int ub() const { return (size — 1); }//upper bound

    • int& operator[](int i); //range checked element

    • vect& operator=(const vect& v); //overload assign

    • vect operator+(const vect& v); //overload add

    • private:

    • int* p;//base pointer

    • int size;//number of elements

    • };


    Safe array with subscripting 2 of 6 l.jpg

    Safe Array with Subscripting (2 of 6)

    • //Add two further constructors

    • //Constructor 1 converts a normal array

    • vect::vect(const int a[], int n)

    • {

    • asert (n > 0);

    • size = n;

    • p = new int[size];

    • assert (p); //throw xalloc;

    • for (int i = 0; i < size; ++i)

    • p[i] = a[i];

    • }


    Safe array with subscripting 3 of 6 l.jpg

    Safe Array with Subscripting (3 of 6)

    • //Constructor 2 is copy constructor

    • vect::vect(const vect& v)

    • {

    • size = v.size;

    • p = new int[size];

    • assert (p);

    • for (int i = 0; i < size; ++i)

    • p[i] = v.p[i];

    • }


    Safe array with subscripting 4 of 6 l.jpg

    Safe Array with Subscripting (4 of 6)

    • The overloaded subscript operator takes an integer argument and tests value is within range

      • If so, it uses it to return the lvalue of the indexed element

  • int& vect::operator[](int i)

  • {

  • if (i < 0 || i > (size — 1)) {

  • cerr << "illegal vect index: "

  • << i << endl;

  • exit(1); //throw boundserr();

  • }

  • //later will use exceptions

  • return (p[i]);

  • }


  • Safe array with subscripting 5 of 6 l.jpg

    Safe Array with Subscripting (5 of 6)

    • vect& vect::operator=(const vect& v)

    • {

    • int s = (size < v.size) ? size : v.size;

    • if (v.size != size)

    • cerr << "copying different size "

    • << "arrays " << size

    • << " and " << v.size << endl;

    • for (int i = 0; i < s; ++i)

    • p[i] = v.p[i];

    • return (*this);

    • }


    Safe array with subscripting 6 of 6 l.jpg

    Safe Array with Subscripting (6 of 6)

    • vect vect::operator+(const vect& v)

    • {

    • int s = (size < v.size) ? size : v.size;

    • vect sum(s); //vect * sumptr = new vect(s);

    • if (v.size != size)

    • cerr << "adding different size "

    • << "arrays " << size

    • << " and " << v.size << endl;

    • for (int i = 0; i < s; ++i)

    • sum.p[i] = p[i] + v.p[i];

    • return (sum); //return (*sumptr);

    • }


    Comments on subscript function l.jpg

    Comments on Subscript Function

    • An overloaded subscript operator has a return type and a single argument

      • It must be a non-static member function

    • It is good style to maintain the consistency between a user-defined meaning of the subscripting operator [] and standard usage

    • A most common function prototype is

  • class name& operator[](integral type);

    • A reference value is returned in such functions that can be used on either side of an assignment expression


  • Shallow copy semantics and vect l.jpg

    Shallow Copy Semantics and vect

    • Provide your own assignment operator anytime pointers are part of the ADT implementation

    • When assignment is not overloaded its default is memberwise assignment of value

      • This is shallow copy semantics and can be incorrect

      • Class provider makes sure that default semantics are correct

      • If not, as is the case here with vect, the class provider must overload the construct with the correct semantics, or alternatively overload the assignment operator with error-signalling behavior


    Comments on assignment function l.jpg

    Comments on Assignment Function

    • The explicit argument v.p[] is the right side of the assignment

    • The implicit argument, as represented by p[], is the left side of the assignment

    • The self-referential pointer is dereferenced and passed back as the value of the expression

      • Allows multiple assignment with right-to-left associativity

    • Function could have been written to return void, but then it would not allow multiple assignment


    Using vect addition and assignment l.jpg

    Using vect Addition and Assignment

    • Meaningful with the extended class vect:

  • a = b;//a, b are type vect

  • a = b = c;//a, b, c are type vect

  • a = vect(data, DSIZE);//convert array data[DSIZE]

  • a = b + a;//assignment and addition

  • a = b + (c = a) + d;//complicated expression

    • The class vect is a full-fledged ADT

    • It behaves and appears in client code much as any built-in type behaves and appears


  • Overloading operator for indexing l.jpg

    Overloading Operator () For Indexing

    • Dynamically allocated two-dimensional arrays can be designed with the function call operator overloaded to provide element selection

      • The matrix is allocated as a column of pointers that are base addresses for a row of elements

    • assert.h provides a macro that dynamically tests a condition and reports on failure

    • The function call operator () is overloadable as a non-static member function

      • Provides an iterator operation or an operation requiring multiple indices


    Overloading 1 of 5 l.jpg

    Overloading () (1 of 5)

    • // Title: matrix

    • #include <assert.h>

    • class matrix {

    • public:

    • matrix(int c, int r);

    • ~matrix();

    • double& operator()(int i, int j) const

    • { return (p[i][j]); }

    • matrix& operator=(const matrix& m);

    • matrix& operator+=(const matrix& m);

    • private:

    • int c_size, r_size;

    • double **p;

    • };


    Overloading 2 of 5 l.jpg

    Overloading () (2 of 5)

    • matrix:: matrix(int c, int r):c_size(c), r_size(r)

    • {

    • assert (c > 0 && r > 0);

    • p = new double*[c];

    • assert (p);

    • for (int i = 0; i < c; ++i) {

    • p[i] = new double[r];

    • assert (p);

    • }

    • }


    Overloading 3 of 5 l.jpg

    Overloading () (3 of 5)

    • matrix:: ~matrix()

    • {

    • for (int i = 0; i < c_size; ++i)

    • delete [] p[i];

    • delete [] p;

    • }


    Overloading 4 of 5 l.jpg

    Overloading () (4 of 5)

    • matrix& matrix::operator=(const matrix& m)

    • {

    • assert(m.c_size == c_size && m.r_size == r_size);

    • int i, j;

    • for (i = 0; i < c_size; ++i)

    • for (j = 0; j < r_size; ++j)

    • p[i][j] = m.p[i][j];

    • return (*this);

    • }


    Overloading 5 of 5 l.jpg

    Overloading () (5 of 5)

    • matrix& matrix::operator+= (const matrix& m)

    • {

    • assert(m.c_size == c_size && m.r_size == r_size);

    • int i, j;

    • for (i = 0; i < c_size; ++i)

    • for (j = 0; j < r_size; ++j)

    • p[i][j] += m.p[i][j];

    • return (*this);

    • }


    Comments on the matrix program 1 of 2 l.jpg

    Comments on the matrix Program (1 of 2)

    • The constructor first allocates an array of pointer-to-double off the heap, then each array of double is allocated with its base address stored in a corresponding element p[i]

      • This scheme is necessary to provide correct addressing to individual matrix components regardless of size

    • The overloaded member function () gives a convenient multiple argument notation for element access which results in client code using expressions of the form m(i,j) to access explicit matrix elements


    Comments on the matrix program 2 of 2 l.jpg

    Comments on the matrix Program (2 of 2)

    • Through an assertion or conditional statement, matrix indices are bounds-tested

    • Assertion macro is used with a precondition for arguments needed by the member function

      • The assertion code replaces an if-else statement that would perform an error exit

    • The matrix being assigned to must be the same size as the matrix expression being computed

    • Dereferencing the this pointer causes the lvalue of the matrix object to be returned


    Overloading new and delete l.jpg

    Overloading new and delete

    • Many classes involve free store memory allocation and deallocation

    • The user of a class wants it to be as flexible and general as possible which can require more sophisticated use of memory than is provided by simple calls to operator new and delete

    • Operators new and delete can be overloaded

      • Provides a simple mechanism for user-defined manipulation of free store


    Memory management overloading l.jpg

    Memory Management Overloading

    • new gets memory

    • delete gets rid of memory

    • Both can be overloaded


    Overloading new and delete82 l.jpg

    Overloading new and delete

    • // Title: alloc

    • //malloc() and free() defined

    • #include <stdlib.h>

    • class X {

    • . . .

    • public:

    • void* operator new(size_t size)

    • { return (malloc(size)); }

    • void operator delete(void* ptr) { free(ptr); }

    • X(unsigned size) { new(size); }

    • ~X() { delete(this); }

    • . . .

    • };


    Comments on the alloc program l.jpg

    Comments on the alloc Program

    • Overloaded forms of new() and delete()

    • When a class overloads operator new(), the global operator is still accessible using the scope resolution operator ::

    • One reason to overload these operators is to give them additional semantics

      • Provides diagnostic information or fault tolerance

    • The class can have a more efficient memory allocation scheme than provided by the system

      • Allocate specific memory pool

      • Defer deallocation and deallocate for a list of objects


    Placement syntax and new l.jpg

    Placement Syntax and new

    • Placement syntax provides a comma-separated argument list used to select an overloaded operator new() with a matching signature

    • Additional arguments are often used to place the constructed object at a particular address

    • This form of new uses the new.h header file

    • Placement syntax allows the user to have an arbitrary signature for overloaded new operator

      • This signature is distinct from initializer arguments used by calls to new that select an appropriate constructor


    Placement syntax and new overloaded l.jpg

    Placement Syntax and new overloaded

    • #include <iostream.h>

    • #include <new.h>

    • char* buf1 = new char[1000];//free store

    • char* buf2 = new char[1000];

    • class object {

    • . . .

    • };

    • main()

    • {

    • object *p = new(buf1) object;//allocate at buf1

    • object *q = new(buf2) object;//allocate at buf2

    • . . .

    • }


    The delete operator l.jpg

    The delete Operator

    • The delete operator comes in two flavors

  • void operator delete(void* p);

  • void operator delete(void* p, size_t);

    • The first signature makes no provision for the number of bytes to be returned by delete

      • Programmer provides code that supplies this value

    • The second signature includes a size_t argument passed to delete which is provided by the compiler as size of object pointed at by p

    • Only one form of delete can be provided as a static member function in each class


  • Using the new h file l.jpg

    Using the new.h File

    • The new.h file has the function pointer _new_handler that calls the error handler for operator new

    • If memory is exhausted, the function pointer _new_handler is calls a default system routine

    • The user can specify an explicit out of free store routine, which can replace the default by using set_new_handler()

    • It is likely in future systems that new will throw an exception when free store is exhausted


    Simple fault tolerance new handler l.jpg

    Simple Fault Tolerance: _new_handler

    • #include <new.h>

    • void heap_exhausted()//user-defined error handling

    • {

    • cerr << "HEAP EXHAUSTED" << endl;

    • exit(1);

    • }

    • main()

    • {

    • set_new_handler(&heap_exhausted);

    • . . .

    • //memory exhaustion is treated

    • //heap_exhausted()

    • };


    Comments on simple fault tolerance l.jpg

    Comments on Simple Fault Tolerance

    • These class new() and delete() member functions are always implicitly static

    • new() is invoked before the object exists and therefore cannot have a this yet

    • delete() is called by the destructor, so the object is already destroyed


    More signature matching l.jpg

    More Signature Matching

    • The function argument type list is called its signature and order of the arguments is crucial

  • int sqr(int i);//int illegal

  • double sqr(int i);//int illegal

  • void print(int i = 0);//int

  • void print(int i, double x);//int, double

  • void print(double y, int i);//double, int

    • When the print function is invoked, the compiler matches the actual arguments to the different signatures and picks the best match


  • Match possibilities l.jpg

    Match Possibilities

    • In general there are three possibilities:

      • a best match

      • an ambiguous match

      • no match

    • Without a best match, the compiler issues an appropriate syntax error


    2 step matching algorithm l.jpg

    2-Step Matching Algorithm

    • The matching algorithm has two parts

    • The first part determines a best match for each argument

      • For a given argument a best match is always an exact match

      • An exact match also includes trivial conversions

    • The second part sees if there is one function that is a unique best match in each argument


    Match types l.jpg

    Match Types

    • void print(int i = 0);

    • void print(int i, double x);

    • void print(double y, int i);

    • print(15);matches int

    • print('A');converts and matches int

    • print(9.90);converts and matches int

    • print(str[]);no match wrong type

    • print(15, 9);ambiguous

    • print(15.0, 9);matches double, int

    • print(15, 9.0);matches int, double

    • print(15.0, 9.0);ambiguous

    • print(i, j, k);no match too many arguments

    • print();match int by default


    Match examples l.jpg

    Match Examples

    Equally GoodNot as Good

    • TT&T*const T*

    • T&TT*volatile T*

    • Tconst TT&const T&

    • Tvolatile TT&volatile T& T[]T*

    • T(args)(*T)(args)

      • The six left-hand trivial conversions cannot be used to disambiguate exact matches


    Promotions and matching l.jpg

    Promotions and Matching

    • The matching rule distinguishes promotions from other standard conversions

    • Promotion goes from narrow type to wider type

      • Going from char to int is a promotion

    • Promotions are better than other standard conversions

    • Among promotions, conversion from float to double and conversion from char, short, or enum to int are better than other promotions

    • Standard conversions include pointer conversions, explained for inheritance


    User defined conversions and matching l.jpg

    User-Defined Conversions and Matching

    • User-defined conversions include constructors of a single argument

    • This constructor can be implicitly called to perform a conversion from the argument type to its class type

    • This can happen for assignment conversions, as in the argument-matching algorithm


    Conversions matching clock 1 of 2 l.jpg

    Conversions & Matching clock (1 of 2)

    • //clock with a reset function

    • class clock {

    • private:

    • unsigned long int tot_secs, secs, mins, hours,days;

    • public:

    • //constructor & conversion

    • clock(unsigned long int i);

    • void print(); //formatted printout

    • void tick(); //add one second

    • clock operator++() {this —> tick(); return(*this);}

    • void reset(const clock& c);

    • //alternate to operator=()

    • };


    Conversions matching clock 2 of 2 l.jpg

    Conversions & Matching clock (2 of 2)

    • void clock::reset(const clock& c)

    • {

    • *this = c;

    • }

    • main()

    • {

    • clock c1(900), c2(400);

    • . . .

    • c1.reset(c2);

    • c2.reset(100);

    • . . .

    • }


    Comments on the clock match l.jpg

    Comments on the clock Match

    • The call to reset(100) involves an argument match between int and clock that is a user-defined conversion invoking the constructor clock(unsigned)

    • Explicitly casting arguments can be both an aid to documentation and a useful way to avoid poorly understood conversion sequences


    Design of a polynomial class l.jpg

    Design of a Polynomial Class

    • What is the public behavior of the ADT?

      • What implementation(s) should be used?Limits?Efficiency?

    • What should its relationship be to other types?

      • Explicit conversions? Implicit conversions?

    • What is expected use of operator overloading?

    • Inheritance and friendship relationships

      • Where are special privileges required?Extensibility concerns?


    Polynomial overload operators 1 of 4 l.jpg

    Polynomial & Overload Operators (1 of 4)

    • class poly {

    • public:

    • poly();

    • poly(const poly& p);

    • poly(int size, double coef[],

    • int expon[]);

    • ~poly() { release(); }

    • void print() const;

    • //evaluate P(x)

    • double operator()(double x) const;


    Polynomial overload operators 2 of 4 l.jpg

    Polynomial & Overload Operators (2 of 4)

    • //Overloaded Operators

    • poly& operator=(const poly& a);

    • friend poly& operator+

    • (const poly& a, const poly& b);

    • friend poly& operator—

    • (const poly& a, const poly& b);

    • friend poly& operator*

    • (const poly& a, const poly& b);

    • friend poly& operator/

    • (const poly& a, const poly& b);

    • friend poly& operator—(const poly& a);//unary

    • friend poly& operator+=

    • (const poly& a, const poly& b);


    Polynomial overload operators 3 of 4 l.jpg

    Polynomial & Overload Operators (3 of 4)

    • friend boolean operator==

    • (const poly& a, const poly& b);

    • friend boolean operator!=

    • (const poly& a, const poly& b);

    • private:

    • term* h;

    • int degree;

    • void prepend(term* t);

    • void add_term(term*& a, term*& b);

    • void release();

    • void rest_of(term* rest);

    • void reverse();

    • };


    Polynomial overload operators 4 of 4 l.jpg

    Polynomial & Overload Operators (4 of 4)

    • poly& poly::operator=(const poly& a)

    • {

    • if (h != a.h) {//avoid a = a case

    • release();//garbage collect old value

    • poly* temp = new poly(a);

    • h = temp —> h;

    • degree = temp —> degree;

    • }

    • return (*this);

    • }


    Comments on the poly class l.jpg

    Comments on the poly Class

    • We expect both the basic mathematical operations to work and the basic relationships among C++ operators to hold

    • It would be very undesirable to have operator=(), operator+(), and operator+=() all defined and not have a = a + b give the same result as a += b


    Summary of ad hoc polymorphism 1 of 4 l.jpg

    Summary of Ad Hoc Polymorphism (1 of 4)

    • A functional notation type-name (expression) is equivalent to a cast

    • A constructor of one argument is de facto a type conversion from the argument's type to the constructor's class type

    • A conversion from a user-specified type to a built-in type can be made by defining a special conversion function

      • Conversions occur implicitly in assignment, arguments to functions, and values returned from functions


    Summary of ad hoc polymorphism 2 of 4 l.jpg

    Summary of Ad Hoc Polymorphism (2 of 4)

    • The overloaded meaning is selected by matching the argument list of the function call to the argument list of the function declaration

    • The algorithm that accomplishes this depends on what type conversions are available

      • 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


    Summary of ad hoc polymorphism 3 of 4 l.jpg

    Summary of Ad Hoc Polymorphism (3 of 4)

    • Keyword friend is a function specifier and it allows a nonmember function access to hidden members of the class of which it is a friend

    • A friend function or an ordinary function has both arguments specified in the parameter list

    • Overloading operators gives them new meanings for ADTs: the ADT can then be used in much the same way as a built-in type

    • Operator overloading uses either member functions or friend functions because they have privileged access


    Summary of ad hoc polymorphism 4 of 4 l.jpg

    Summary of Ad Hoc Polymorphism (4 of 4)

    • When a unary operator is overloaded using a member function, it has an empty argument list: single operator argument is implicit

    • When a binary operator is overloaded using a member function, its 1st argument is the implicitly passed class variable and its 2nd is the lone argument list parameter

    • Overloaded subscript, assignment, function call, and member access must be non-static member functions

    • new and delete can be overloaded for user-defined manipulation of free store


    Slide110 l.jpg

    110

    110


  • Login