First | Next | Previous | Last | Glossary | About |
We now finish most of the work with functions by looking at some topics which tend to set C and C++ apart from many other languages.
//Example 1 - default arguments #include <iostream> #include <time.h> #include <stdlib.h> float read_floats( float [100], int start = 10, int stop = 20); int main() { float a[100]; srand (time (0)); for (int i = 0; i < 100; i++) a[i] = rand(); cout << read_floats(a,19) << endl; cout << read_floats(a) << endl; cout << read_floats(a,83,94) << endl; return 1; } float read_floats(float a[], int start, int stop) { int i; float total = 0; cout << "Summing " << start << " to " << stop << " "; for (i = start; i <= stop; total = total + a[i], i++); return total; }
Assume you have created a function to add a number of values in an array, for instance the array might contain 100 floats. Your function takes a starting index (start) and a finishing index (stop) and sums the floats over the range start to stop.
We can declare a function and initialise its arguments:
float read_floats( float [], int start = 10, int stop = 20);
Now if we call the function like this:
cout << read_floats(a) << endl;
that is, supplying only the first argument, the start and stop arguments will take the default values.
We can also supply just one of the default arguments:
cout << read_floats(a,19) << endl;
But we can't do this:
cout << read_floats(a,,19) << endl;
Arguments can't be "defaulted" and then followed by a non-default argument.
Try the example program first and make sure that it works.
Exercise 1.2Example 1 is quite a dangerous little program. What is wrong with the following calls to read_floats():
Modify Example 1 so that the start and stop arguments are never out of range and start is always less than or equal to stop.
What simple modification could be made to read_floats() so that it could manage arrays of an undefined size? There is a sample answer here if you get stuck.
//Bad Identifier #include <iostream> int main() { int i = 0; //i1 {int i = 5;} //i2 int i = 10; //i3 return 0; } bad_id.cc: In function `int main()': bad_id.cc:9: redeclaration of `int i' bad_id.cc:5: `int i' previously declared here
C and C++ don't normally allow you to declare the same identifier more than once in the same scope.
The example shows that we can declare an identifier with the same name but in different scopes. Identifiers i1 and i2 are quite OK. However i3 will create the error message bad_id.cc:9: redeclaration of `int i'.
// Function overloading #include <iostream> #include <iomanip> int add_values(int a, int b) { return (a + b); } int add_values(int a, int b, int c) { return(a + b + c); } float add_values(double a, double b) { return a + b; } float add_values(double a, int b) { return a + b; } void main(void) { cout << "100 + 801 = " << setw(4) << add_values(100, 801) << endl; cout << "100 + 201 + 700 = " << setw(4) << add_values(100,201,700) << endl; cout << "11.74 + 22.37 = " << add_values(11.74, 22.37) << endl; cout << "11.74 + 22 = " << add_values(11.74, 22) << endl; }
The situation is different with functions. Functions can have the same identifier in the same scope but be quite different functions. For instance you might have several functions all called add_values() but you can ensure each function is different by ensuring each function has a different argument list.
Here we have four functions called add_values() but each has different arguments. When this program is compiled the compiler will generate different signatures for each of the functions based on the function name and the argument list.
If similarly named functions have different signatures then they are different functions.
Is function overloading a good thing? It's certainly useful to be able to call functions which do the same things with different data types and once the program is running everything works fine. The major problem is a coding time problem - making sure that you call the correct function with the correct arguments.
Try the example program first and make sure that it works.
#include <iostream> #include <stdarg.h> void varints(int , ... ); void varstrings(int , ... ); void main(void) { varints(3,1,2,3); varints(7,1,2,3,4,5,6,7); varstrings(3, "David", "Robert", "Beech"); } void varints(int a, ... ) { va_list argument; va_start(argument, a); cout << "Function has " << a << " arguments\n"; for (int count = 0; count < a; count++) cout << va_arg(argument, int) << " "; cout << endl; va_end(argument); } void varstrings(int a, ... ) { va_list argument; va_start(argument, a); cout << "Function has " << a << " arguments\n"; for (int count = 0; count < a; count++) cout << va_arg(argument, char *) << " "; cout << endl; va_end(argument); }
You are used to fastidiously ensuring that when you call a function you match each of the actual parameters with each of the function arguments but ... a function can have a variable number of arguments!
To create and use functions with an arbitrary number of arguments we:
void naughty_float(int argc, ...) { va_list arguments; va_start(arguments, argc); for (int i = 0; i < argc; i++) cout << va_arg(arguments, float) << endl; va_end(arguments); } void nice_float(int argc, ...) { va_list arguments; va_start(arguments, argc); for (int i = 0; i < argc; i++) cout << va_arg(arguments, double) << endl; va_end(arguments); }
There is a small catch with using va_arg() which this example shows. The second argument to va_arg() should not be a "promotable" data type, ie use double rather than float and integer rather than short. If you try the example functions out you will see what I mean.
The va_arg() macro must make some decisions about the size of the datatype of the argument that will be extracted from the argument list. This means that floats are treated like doubles and shorts like integers. If the compiler treats float and double as the same size and short and int as the same size then there probably won't be a problem. It's not an issue I understand clearly myself but I have told you about it. My duty is done.
Try the first example program and make sure it works.
Exercise 3.2If you haven't already done so use the two functions naughty_float() and nice_float() in a program and compare the results. Why do they differ?
Exercise 3.3Write a program which takes a variable number of integers from the keyboard and which sums the integers.
First | Next | Previous | Last | Glossary | About |
Copyright © 1999 - 2001
David Beech