oop etgar 2008 – recitation 51 object oriented programming etgar 2008 recitation 5
Post on 20-Dec-2015
216 views
TRANSCRIPT
OOP Etgar 2008 – Recitation 5 1
Object Oriented Programming
Etgar 2008Recitation 5
OOP Etgar 2008 – Recitation 5 2
Function Pointers
A good tutorial is athttp://www.newty.de/fpt/
OOP Etgar 2008 – Recitation 5 3
Can We Increase Grades?
• Assume we have a list of all student grades for the OOP course, and we would like to increase each and every one of them.
• The list is in the GradesList data structure that is accessed by GradesList::get(ID) and GradesList::set(ID, grade).
• Calling get()/set() for each student is tedious.• How can we tell the GradesList to apply
some function to each of its members?
OOP Etgar 2008 – Recitation 5 4
The Solution• If GradesList had a function
GradesList::ApplyToAll() we’d be done – but what if we don’t know in advance what function to apply?
• A function pointer is what we need – a way to tell GradesList::ApplyToAll() which function to use.
OOP Etgar 2008 – Recitation 5 5
Function Pointers – Possible?
• We can think of a function name as a pointer to where its code begins.
• Thus func is a memory address of where the code of func() begins.
• But since a function has arguments and return value, the type of the pointer must specify them.
OOP Etgar 2008 – Recitation 5 6
Function Pointers• A pointer to a function with no arguments
and returning an int is declared asint (*p)();
• Read it inside out – p is a pointer (the *) to a function (the right-hand ()) taking nothing (these parenthesis are empty) and returning an int.
• The parenthesis around *p are needed to ensure that * is “applied” before ().
OOP Etgar 2008 – Recitation 5 7
The Syntax• If idler() is defined as
int idler();
we can writep = idler;
• p now points to the beginning of the code of idler().
• To run that code using p, type(*p)();
or in shortp();
OOP Etgar 2008 – Recitation 5 8
More Complex Syntax• The list of arguments is specified in the
right-hand parenthesis.• If pow() is defined as
double pow(double b, double p);
the correct pointer isdouble (*pow_p)(double, double);
• The calling syntax is the same:pow_p = pow;pow_p(1.2, 2.3);
OOP Etgar 2008 – Recitation 5 9
Typedef• Function pointer syntax is complex,
especially when the function itself returns a function pointer. Use typedefs to simplify:
typedef double (*func_p)(double, double);
• func_p is a type of a pointer to a function taking two doubles and returning an int.
• Variable declaration now is more readable:func_p p = pow;p(1.2, 2.3);
OOP Etgar 2008 – Recitation 5 10
Back to the Beginning• Now the grades can be increased:
int ten_percent(int grade) {return grade*1.1;
}
void GradesList::ApplyToAll( int (*f)(int) );
grades.ApplyToAll(ten_percent);
OOP Etgar 2008 – Recitation 5 11
(Extremely) Complex Example
• Define a variable of type “array of N pointers to functions returning pointers to functions returning pointers to char”.
Huh?
• The straightforward (and unreadable) solution:
char *(*(*a[N])())();
OOP Etgar 2008 – Recitation 5 12
Solution with Typedefstypedef char *pc; /* pointer to char */
typedef pc fpc(); /* function returning pointer to char */
typedef fpc *pfpc; /* pointer to above */
typedef pfpc fpfpc(); /* function returning... */
typedef fpfpc *pfpfpc; /* pointer to... */
pfpfpc a[N]; /* array of... */
From “C FAQs” by Steve Summit.
OOP Etgar 2008 – Recitation 5 13
Pointers to Members
OOP Etgar 2008 – Recitation 5 14
Non-Static Member Functions
• Just as we can declare a pointer to a function, we can declare a pointer to a non-static member function.
• The syntax is different, since non-static member function takes an implicit this parameter.
• The type of a pointer to non-static member function must include class specification, and the method invocation must be done on an object.
OOP Etgar 2008 – Recitation 5 15
Examplestruct C {
void func(); // (1)void func() const; // (2)void func(int); // (3)
};…
C temp; // temp is an object of class C
void (C::* p1)(); // pointers to members of C
void (C::* p2)() const; // …void (C::* p3)(int); // …
p1 = C::func;p2 = C::func;p3 = C::func;(temp.*p1)(); // invocation of (1)(temp.*p2)(); // invocation of (2)(temp.*p3)(3); // invocation of (3)
OOP Etgar 2008 – Recitation 5 16
Notes• As always, typedefs will simplify reading:
typedef void (C::* Cptr)();Cptr cp = C::func;
• Pointers to static member functions are regular function pointers.
OOP Etgar 2008 – Recitation 5 17
Pointers to Data Members
• Pointers to class data members should be specified with a class name.
struct C {int i;
};…C temp; // object
of type Cint C::* p; // pointer
to C's int data//
memberp = &C::i; // p points
to icout << temp.*p; // prints temp.I
OOP Etgar 2008 – Recitation 5 18
Templates
Generic Programming
OOP Etgar 2008 – Recitation 5 19
Why?• Often we meet algorithms, data
structures or classes that are independent of the concrete type used in them.
• QuickSort can sort anything (if it can be compared).
• List can store anything.• But how can we write generic algorithms
and data structures?
OOP Etgar 2008 – Recitation 5 20
Bad Solutions• Using void* pointers:
– Type-unsafe.– Error-prone.– Very unfriendly.
• Deriving all classes from one superclass:– Type-unsafe.– Demands specific interface from all classes.
• Both solutions disallow homogenous containers.
OOP Etgar 2008 – Recitation 5 21
Templates• A template allows passing a type as a
parameter to a class or a function.• This means that we can write classes and
functions that are independent of the types they work with.
• Actually, a template is a recipe for creating families of classes and functions.
OOP Etgar 2008 – Recitation 5 22
Swap()• Consider the function swap() – the code is
identical if it swaps two ints, two Rationals or two strings.
void swap(int& a, int& b) {int temp = a;a = b;b = temp;
}
OOP Etgar 2008 – Recitation 5 23
Function Templates• We can say that to the compiler by
defining a function template:template <typename T>void swap(T& a, T& b) {
T temp = a;a = b;b = temp;
}
• Within the template, T is another type, just like int or double.
OOP Etgar 2008 – Recitation 5 24
Template Instantiation• The compiler will use this template to
instantiate swap() for types it needs:– When it needs to swap ints, it will generate a
version for ints.– If it needs to swap strings, it will generate a
new version for strings.
• The versions it generates will have no connection to one another (apart from similar name).
OOP Etgar 2008 – Recitation 5 25
Lack of Conversions• The compiler decides which version to instantiate
based on the parameters types.– This is called template argument deduction.
• Conversions are not considered for this.– I.e., these calls will not compile:
int i; short s; double d;swap(i, d); // no version
for int and a doubleswap(i, s); // no version
for int and a short
• The only conversions used are– conversion to const pointer or reference,– array and function to pointer.
OOP Etgar 2008 – Recitation 5 26
Class Templates• What about classes? Obviously, the code
for ListOComplex will work for Rationals, ints or strings, if we didn’t hardwire the type into it.
• We can define a class template for a List, and List users will specify the concrete type when creating List objects.– The compiler will create instantiated classes
as needed.
OOP Etgar 2008 – Recitation 5 27
Class Listtemplate <typename T>class List {public:
List(const List&);bool push_front(const T&);T pop_front();…
};
• Within List’s methods, T is another type, just like int or double.
OOP Etgar 2008 – Recitation 5 28
Instantiated Classes• With class templates we need to specify the type
parameter to create an object:List<Complex> listOcomplex;List<int> listOint;
• The compiler creates an instance of class List for Complexes and an instance for ints.
• They have nothing to do with one another.• Note that copy c’tor in List has a parameter of
type List, not List<T>.– Both forms can be used – but the former only within the
template itself.
OOP Etgar 2008 – Recitation 5 29
Notes• Templates can be complicated:
– Referring to base class template from within a derived class template requires the use of this->, using or ::.
– Care should be taken for templates within templates – the >> in List<vector<int>> is interpreted as operator>>().
• But templates allow generic programming.
• In fact, templates themselves form a complete programming language.