View
222
Download
0
Category
Tags:
Preview:
Citation preview
Copyright © 2006-2012 - Curt Hill
Functions
Additional Topics
Topics to be Discussed
• Default Parameters• Function Signatures• Function Name Overloading• Inline Functions• Template Functions• Variable number of parameters• Testing• Why use functions? Again!
Copyright © 2006-2012 - Curt Hill
Copyright © 2006-2012 - Curt Hill
Default parameters• Something new in C++ is default
arguments• There is a feature that you can
initialize an argument that was omitted from the call
• Effectively this gives a function that may have variable number of parameters
Copyright © 2006-2012 - Curt Hill
Example:
• Declaration:– int fn(int a = 5) ...
• Call– fn(5) and fn() are exactly the same
• Call– fn(2) would be different
• A parameter list must be supplied– Sometimes it can be empty
Copyright © 2006-2012 - Curt Hill
Rules and Regulations
• There may be multiple default arguments
• int fn(double x = 45.3, int i = 5, int j=10)– May be called with 0, 1, 2, 3
arguments
• An omitted argument must be last– fn(2.4,5) supplies x and i lets j
become 10– fn(3.2,,4) is not legal
Copyright © 2006-2012 - Curt Hill
More• You may mix defaulted and non-
defaulted parameters, but all the defaults must be to right of all the others– int fn(float a, int b, int c = 5, char d =
'a')
• The allowable types of default parameters includes anything suitable for assignment
• If you use a prototype, it must appear there and not in header
Copyright © 2006-2012 - Curt Hill
Prototypes and headers• The rules of C++ indicate that we must declare
something before we use it• For functions this can be accomplished in two
ways:– Put the entire function definition in the code before the
call– Code a function prototype first and the function later
• Former means that we have upside down programs– The first thing to be executed is the last thing to be
seen and the first thing seen can call nothing
• The latter mechanism is useful for organizing our programs in top down ways
• Requires a prototype and a header
Copyright © 2006-2012 - Curt Hill
Prototypes
• A function prototype is (mostly) the function header plus a semicolon instead of the function body
• The purpose of the prototype is to declare it without defining it
• The C or C++ compiler will not complain:– If he sees a prototype without a definition– If he sees multiple prototypes for the same
function– However, if there is a prototype without
definition then the linker gets unhappy
Copyright © 2006-2012 - Curt Hill
More• A prototype gives just enough
information for the function to be called, but does not define what the function does– The prototype can leave out the parameter
names, whereas a header can not– No calling function can access the names so
why bother to specify them, except for documentation?
• The prototype can be local to a function– Though is not usually done– Only that function can then access it
Copyright © 2006-2012 - Curt Hill
Two main uses of prototypes• Documentation
– After the includes, provide a prototype for each function– Typically one line per function– Followed by the main function– Reader can view the function declaration along with the
code that references them– The prototypes can be in any order, even alphabetical– You can compile, even without all of the function
definitions, but not execute• Headers and libraries
– A header file, usually includes only the prototypes– This way we can call it without having to recompile the
function itself– The linker finds the object (machine language) for the
function– Hence the function can be used by someone, yet still
maintain the privacy and efficiency of separately compiled and hidden source code
Copyright © 2006-2012 - Curt Hill
C function names
• A C function was recognized by precisely one thing: its function name– A variable and a function may have
the same name• C distinguishes by the absence of
parentheses following the variable
– Only one named function X may be available
Copyright © 2006-2012 - Curt Hill
Function signatures• New in C++• C++ looks at the entire call of a
function:– Function name– Types of the parameters to a function– Result type is not considered
• Two functions are different if their signatures are different– Which could mean their names are the
same– This will come in very handy with
classes
Copyright © 2006-2012 - Curt Hill
Examples• Thus there is no problem with defining
the following:– int i,j; double x,y;– int add(int a, int b);– double add(double a, double b);
• i = add(i,j) is the first• x = add(x,y) is the second• x = add(i,x) is a problem(although not
an error) for there is no really obvious way to handle it
Copyright © 2006-2012 - Curt Hill
Commentary• This will also enable operator
overloading, which we will investigate fully when we deal with classes
• Why is the return value type is not significant?– That type cannot be determined from the
call– The return value could be ignored or cast
into another type
• How does casting affect this mechanism
Copyright © 2006-2012 - Curt Hill
Casting• The function call matching mechanism
of C++ is much more complicated than previous languages– It actually searches through possibilities
• While we try to resolve the duplicates, there are a number of promotions that we can apply to make the signature match
• These include widening and conversion• The best policy is always an exact
match
Copyright © 2006-2012 - Curt Hill
Widening• Sometimes we can convert an
integer by widening, that is converting from one type to a similar type without loss of information
• Examples:– char to int– float to double– short to int
• These are nice since we never lose any information
Copyright © 2006-2012 - Curt Hill
Conversions:• We can change from one type to another
type if the target type is stronger• The hierarchy of types is from weakest to
strongest:– char– int– unsigned– long– unsigned long– float– double– long double
Copyright © 2006-2012 - Curt Hill
Promotions
• The standard promotions are to– Attempt widening– Attempt strengthening weaker to
stronger
• Constructors form another possibility that will be dealt with later– A constructor creates an object– Also known as a user defined
conversion
Copyright © 2006-2012 - Curt Hill
Ambiguous Match
• Most others languages offer a clean hit or clean miss for function identification
• C++ does not• Instead C++ searches for the best
function match• We can end at an ambiguous
match and this gives an error• Consider this example:
Copyright © 2006-2012 - Curt Hill
Example• int fn(int a, double b);int fn(double a, int b);x = fn(2, 5);
• This is an ambiguous match– The first one can be matched by
converting the 5– The second one by converting the 2
• Thus they are equally far from the call
• C++ will give an error– The programmer can choose by doing
a manual cast: x=fn(double(2),5);
Copyright © 2006-2012 - Curt Hill
Here are the rules:• Use an exact match if found
• Try widening• Try conversions• Try user defined conversions
(constructors)
– If there are two matches that are equally far from the current, then the call is ruled ambiguous and a syntax error is announced:
• Generally the programmer should code an exact match
Variable numbers of parameters
• The C stream input/output system had a couple of functions that look really strange:printf(“Answers: %d, %lf\n”,i, x);
• The funny part is that this always required an initial string
• After that it could have as many parameters as needed
• Each parameter replaced a format descriptor
Copyright © 2006-2012 - Curt Hill
Types
• The problem with this approach was that there was no way to verify type
• The %d stated that an integer was expected– There was no way to verify this
• It is a type-insecure system• This system will be covered later but
what is of interest is how to declare an unknown number of parameters
Copyright © 2006-2012 - Curt Hill
The Ellipsis
• The function header contains three dots to signify that we do not know how many parameter follow
• Thus the printf header looks like this:int printf(char * f, …);
• The comma before the ellipsis is optional
Copyright © 2006-2012 - Curt Hill
Problems
• Just because we have variable number of parameters does mean that we can use them
• How are they referenced in the code?– There are no names– There are no types– There is not even a count of how
many there are
Copyright © 2006-2012 - Curt Hill
Macros
• There are several macros that allow us to handle these
• A macro is something done by the preprocessor– We will consider preprocessor macros
later
• In order to enable these we need the include of stdarg.h
• All of the items start with va_– Variable Args
Copyright © 2006-2012 - Curt Hill
va_ Items• va_list – a type to hold the progress• va_start – function to initialize the
va_list item– Parms: the va_list item and named
parameter
• va_args – function to obtain the next argument– Parms: the va_list item and type to be
returned
• va_end – stop the iteration through the arguments
Copyright © 2006-2012 - Curt Hill
Example 1
Copyright © 2006-2012 - Curt Hill
int sum1(int count, ...){ int res = 0; va_list arg_ptr; int args = 0; va_start(arg_ptr,count); while(args++ < count){ res += va_arg(arg_ptr,int); } va_end(arg_ptr); return res;}int i = sum1(4,2,3,4,5);
Example 2
Copyright © 2006-2012 - Curt Hill
int sum2(int first ...){ int res = first,arg; va_list arg_ptr; va_start(arg_ptr,first); while(true){ arg = va_arg(arg_ptr,int); if(arg<0) break; res += arg; } va_end(arg_ptr); return res;}b = sum2(1,1,1,1,1,1,1,1,-1);
Notes
• There must be some way to know when to stop looking for parameters
• printf counts directives• sum1 used the first parameter as a
count• sum2 kept going until a negative
was found• Any technique based on the
function logic works
Copyright © 2006-2012 - Curt Hill
Ellipsis vs. Defaults
• Default parameters – Give us a range of parameters to be
given– Specifies the types and what values
to supply if left out– There is a maximum number of
parameters, specified in header
• Ellipsis– No types are given– No maximum
Copyright © 2006-2012 - Curt Hill
Copyright © 2006-2012 - Curt Hill
A problem
• Sometimes we end up with a function that is very short because – Stepwise refinement gave us a
shorter function than we thought– It is used frequently in the program
• The function call overhead could be larger than the work done in the function
• For such functions it is less efficient
Copyright © 2006-2012 - Curt Hill
Example• Swap• Take two values and exchange
them:void swap(int & a, int & b){ int temp = a; a = b; b = temp; }
• There are three statements to call one or two to return but only three in the function
Copyright © 2006-2012 - Curt Hill
Inline functions• A function may be preceded by the
keyword inline• This causes the function to be macro
expanded rather than called in the code
• Handy for very short functions, where the overhead of a function call may be too large compared to the execution of the function
• This is handier with classes, but the swap function makes a nice candidate
Copyright © 2006-2012 - Curt Hill
Example•Swap made an inline function:inline void swap(int & a, int & b){ int temp = a; a = b; b = temp; }
Copyright © 2006-2012 - Curt Hill
Tradeoffs• In computer science we have a
common space speed tradeoff• We can usually make something
smaller but at the cost of making it slower or faster but at the cost of making it larger
• This happens with inline as well• An inline function that is called
several times will be faster but larger than the non-inline version
Copyright © 2006-2012 - Curt Hill
Another Problem
• C++ and Java allow function name overloading but our tools predate their use
• In particular the linker agrees with C that a function name alone determines the function to use
• Thus C++ uses a process called name mangling to make the names unique
Copyright © 2006-2012 - Curt Hill
Name Mangling
• The C++ compiler generates a unique name for each function
• This name contains the function name and all the parameters types in order
• This may only be seen in the linker output
• Most debuggers handle this by giving the original name
Copyright © 2006-2012 - Curt Hill
Testing strategies
• Functions allow two new testing approaches:– Bottom up – Top down
• Besides that we have another categorization of testing:– Black box– White box
Copyright © 2006-2012 - Curt Hill
Bottom Up Testing
• Each function has its own specifications
• These can be tested independently of the rest of the program
• Write a driver program that calls the function– Multiple calls– Each result is checked for correctness– Still use statement / path testing
Copyright © 2006-2012 - Curt Hill
Moving up
• When the bottom functions are tested then move up a level to those functions that call them
• When the main program is tested then you are done
• It is also a smart thing to retain the driver programs for tests on the functions when they change
• This is important in XP
Copyright © 2006-2012 - Curt Hill
XP• Not Windows XP but eXtreme
Programming• One of the precepts of XP is
individualized testing• Each object type has its own
automated driver that tests the class in all reasonable ways
• These drivers are maintained so that when any change is made in the class the test is performed
• This is a variation of Bottom Up testing
Copyright © 2006-2012 - Curt Hill
Top Down Testing• You may test the main function
before the lower functions are coded
• This allows a program to be coded by different programmers
• Create stub functions• The stub function emulates the real
function, which may not yet be done
• Allows the main to be tested whenever it its ready
Copyright © 2006-2012 - Curt Hill
Stub Functions• These are created with one of
several approaches:• Have it respond to fixed test data
– A function that always returns 2.5 because that is what is should on this set of test data
• Have it display its parameter values and ask a person for the right answer
• Only way to test if the sub-functions are incomplete
Copyright © 2006-2012 - Curt Hill
Black Box Testing
• No knowledge of the interior structure of a program or function
• This kind of test data usually comes from the people who will actually use the program
• It may be made up in advance before the coding even starts
• Another one of the precepts of XP
Copyright © 2006-2012 - Curt Hill
White Box Testing
• Test data provided by someone with knowledge of the code
• Every statement and every path testing are examples
• The programmer has a good idea what kind of data may cause the function to abort or return wrong results
Copyright © 2006-2012 - Curt Hill
Advantages of functions
• Economy• Readability• Maximum efficiency of stepwise
refinement• Code reuse• Code localization
Copyright © 2006-2012 - Curt Hill
Economy
• Instead of making two or more copies of the same code we can just code it once
• Parameters allow us to take two pieces of code which are almost the same and make into one parameterized function
• For example the change program
Copyright © 2006-2012 - Curt Hill
Recall the change program
• Given purchase price, tendered amount find the number of twenties, tens, etc.
• There was a loop for twenties, tens, and every other denomination of coin or bill
• However all the loops were the same with small changes:
Copyright © 2006-2012 - Curt Hill
Some of the codeint twenties = 0;while(change > 20) { twenties++; change -= 20; }if(twenties > 0) cout << “Give the customer “ <<twenties << “twenties.”;int tens = 0;while(change > 10) { tens++; change -= 10; }if(tens > 0) cout << “Give the customer “ <<tens << “tens.”;
Copyright © 2006-2012 - Curt Hill
Improvements
• We can generalize this code by changing three things:– twenties or tens– 20 or 10– “twenties” or “tens”– change stays the same
• Lets look again
Copyright © 2006-2012 - Curt Hill
Color Coded Similaritiesint twenties = 0;while(change > 20) { twenties++; change -= 20; }if(twenties > 0) cout << “Give the customer “ << twenties << “twenties.”;int tens = 0;while(change > 10) { tens++; change -= 10; }if(tens > 0) cout << “Give the customer “ << tens << “tens.”;
Copyright © 2006-2012 - Curt Hill
Solution
• Make the code a parameterized function
• This is called repeatedly from the main program
Copyright © 2006-2012 - Curt Hill
The Economized Codevoid changer(double & change, int size, AnsiString label){ int count = 0; while(change > size) { count++; change -= size; } if(count > 0) cout << “Give the customer “ << count << label.c_str();}...changer(change, 20, ” twenties”);changer(change, 10, ” tens”);changer(change, 5, ” fives”);changer(change, 1, ” ones”);
Copyright © 2006-2012 - Curt Hill
Readability• When we read the main program we no
longer have to wade through each version of the change loop– We can just notice that we call changer
• Our minds allow us to conceptualize items– We think of making change for one
denomination not as a series of steps but as one abstract action
– We we can view the function as a single item without worrying how we do it.
– Keeps the number of chunks we are currently concerned with lower
– We think about what not how
Copyright © 2006-2012 - Curt Hill
Readability rule
• A function should not be longer than a page– This used to be a page of printed
output– Today is is one screen in the editor
• If it is longer make it into two or more functions
• Threat– From now on you had better use
functions
Copyright © 2006-2012 - Curt Hill
Maximum Efficiency of Stepwise Refinement
• Make our English statements into function names
• The main program or event handler takes one pass
• All the separate functions are then smaller
• We do not care if any of these are reusable
• What we want is easy to design
Copyright © 2006-2012 - Curt Hill
Code reuse• A future program may require one of
our functions:– factorial– change
• Do not write it again but copy it from somewhere else
• The includes bring in groups of functions that we do not want to write again
• Established programming shops have libraries of functions that they have found to be useful
• Do not re-invent the wheel
Copyright © 2006-2012 - Curt Hill
Code Localization
• Makes modifications somewhat easier
• Reduces coupling• Often the case that only a
single function will touch a file• When the file format is
changed only this routine needs changing– No need to scan whole program
looking for references to the file
Recommended