CS 596 OODP
C++ Functions
[To Lecture Notes Index]
San Diego State University -- This page last updated August 21, 1995

Contents of C++ Functions Lecture
- References
- Functions
- Default Parameters
- Overloading Functions
- Inline Functions
- Template (Generic) Functions
- Scope
- Pointers to Functions
- Ellipses - Variable number of Arguments
- New - Delete
C++ Primer, Lippman. Sections 3.2, 3.5, 3.6, 3.7, 3.8, 3.9, 3.11,
chapter 4
C++ checks all parameter usage
C does not check parameter usage
void GoodBye(char* Message) {
cout << "Good Luck" << Message << endl;
}
Return Value
- Use void if there will be no value returned
Public Interface
- Return value and argument list of a function
Signature
- Argument list of a function
The signature and name of a function are used to uniquely identify the function.
Forward Declaration of Function
#include <iostream.h>
int min(int a, int b); // a signature
int max(int, int); // no parameter names needed
int goofy(int why, int not); // trouble ahead
main() {
cout << min(2, 5) << "\n";
}
int min(int a, int b) {
return a < b ? a : b;
}
int max(int a, int b) {
return a > b ? a : b;
}
int goofy(int confuse, int me) {
cout << "This is legal, but confusing" << endl;
return confuse;
}
C++ Only
int MyTest( int a, int b = 1, char c = 'a') {
return ( a + b + c);
}
main()
{
int x;
x = MyTest(4);
x = MyTest(3, 1);
x = MyTest(2 ,1 , 'x');
x = MyTest(2, 'x'); // Not what you think!
}
- Default arguments are to the right of non default arguments
-
- In function call, if parameter uses default value, all arguments to the
right must also use default value
Default Parameters
With Forward declaration
int min(int a, int b = 10);
int min(int a, int b) { // no default needed here
return a> b ? a : b;
}
C++ Only
#include <iostream.h>
void overLoadedCall(int a) {
cout << "Who's on first?\n";
}
void overLoadedCall(float a) {
cout << "Where is second?\n";
}
main(){
int a;
float b;
overLoadedCall(b); // prints Where is second?
overLoadedCall(a); // prints Who's on first?
}
Say What?
main(){
char a;
double b;
overLoadedCall(b); // prints Where is second?
overLoadedCall(a); // prints Who's on first?
}
Rules for Finding Correct Overloaded Function
One Argument
1) Look for exact match between formal and actual arguments
2) Promote actual argument and look for match
Actual Formal
char int
unsigned char int
short int
unsigned short int (if int > short)
unsigned int (otherwise)
float double
eumerated int
3) Match by Standard Conversion
Actual Formal
any numeric type any other numeric type
eumerated any numeric type
zero pointer or numeric type
pointer void*
Rules for Finding Correct Overloaded Function
Multiple Arguments
Pick the function for which the resolution of each argument is the same or
better than for all other functions of the same name and it must be strictly
better than all other functions for at least one argument. A function is
ambiguous is no one function instance contains a better match or if more
than one function instance contains a better match.
void ItsMe( char*, int );
void ItsMe( int, int );
ItsMe( 0, 'a' ); // ItsMe(int, int) best match
void dont( long, long );
void dont( double, double );
int give, up;
dont( give, up ); // ambiguous, compile error
void you( int, int );
void you( float, float );
int fooled;
float me;
you( fooled, me ) // ambiguous, compile error
OverLoading Problems
Return value not used to identify function
int ReturnDoesNotCount(int dont) {
cout << "Big" << endl;
return 5;
}
float ReturnDoesNotCount(int doIt) { // compile error
cout << "Mistake" << endl;
return 5.5;
}
main() {
float whichOne;
whichOne = ReturnDoesNotCount(2);
}
OverLoading Problems
Default values
int OverLoadAndDefault(int dont, float doIt = 5.5) {
cout << "Big" << endl;
return 5;
}
int OverLoadAndDefault(int dont, int doIt = 5) {
cout << "Mistake" << endl;
return 10;
}
main() {
int whichOne;
whichOne = OverLoadAndDefault(2, 3); // OK
}
main() {
int whichOne;
whichOne = OverLoadAndDefault(2); // compile error
}
C++ Only
inline int Max(int x, int y) {
return (x > y ? x : y);
}
main()
{
int a = 5 , b = 3;
a = Max(a,b);
}
becomes
main()
{
int a = 5 , b = 3;
int LocalX = a;
int LocalY = b
a = LocalX > LocalY ? LocalY : LocalX ;
}
What is Wrong with Macros?
#include <iostream.h>
#define product( a, b ) a*b
#define MadMax( a, b, c) ((a > b) & (a > c) ? a : b)
main() {
int X = 5;
int Y = 10;
cout << product ( X + 1, Y + 2) ; // prints 17
cout << MadMax(Y++, X, X); // prints 12
}
C++ Only
template <class MyType>
MyType min( MyType a, MyType b) {
return a < b ? a : b;
}
main() {
int a = 1, b = 2;
float c = 1.1, d = 2.2;
int e[10], f[10];
cout << min(a,b) // prints 1
<< "\n"
<< min(c,d) // prints 1.1
<< "\n"
<< min(e, f); // no < operator on arrays
// compile error (I hope)
}
Template functions can be overloaded
Added after AT&T V2 of C++
C++ Only
:: - use global variable
#include <iostream.h>
int where = 10;
main()
{
int where = 5;
cout << ::where // prints 10
<< "\n"
<< where // prints 5
<< "\n";
}
void quickSort( int* array, int LowBound, int HighBound)
{
// source code to sort array from LowBound to HighBound
// using quicksort has been removed to save room on page
}
void mergeSort(int* array, int LowBound, int HighBound)
{ // same here}
void insertionSort(int* array, int LowBound, int HighBound)
{ // ditto }
void main()
{
void (*sort) (int*, int, int); // Pointer to function
int Size;
int Data[100];
// pretend Data and Size are initialized
if (Size < 25)
sort = insertionSort;
else if (Size > 100)
sort = quickSort;
else
sort = mergeSort;
sort(Data, 0, 99);
}
Arrays Function Pointers
void DoNothing() { // put no code here }
void HaveFun() { // No room on page for source code }
void Trouble() { // same here }
void Check() { // ditto }
int GetMenuItemSelected()
{
// Returns zero if no items are selected
// otherwise return the number of the menu item selected
}
main()
{
void (*menuActions[]) () =
{
DoNothing,
HaveFun,
Check,
Trouble
};
menuActions[GetMenuItemSelected()];
}
#include <iostream.h
#include <stdarg.h>
// This sums up a list of integers.
// The last integer must be zero.
long int sum( int MyArg,...)
{
va_list ap; int next; long int total = MyArg;
va_start( ap, MyArg); // Must call va_start,
// Second parameter must be last
// named parameter in sum
while (next=va_arg(ap,int))
total += next;
va_end( ap ); // Needed for clean up
return( total );
}
void main()
{
long int result;
result = sum( 2, 4, 6, 8, 0 );
cout << "The sum of 2, 4, 6, and 8 is " << result;
}
Memory from the Heap
#include <iostream.h>
main() {
int *noWhere;
noWhere = new int; // allocate space
*noWhere = 5;
cout << *noWhere << "\n";
delete noWhere; // deallocate space
}
Function Pointers and New
#include <iostream.h>
#include <stdlib.h> // For exit
#include <new.h> // For set_new_handler
void OutOfMemory()
{
cerr << "Ran out of memory. Good Bye!"
<< endl;
exit(1);
};
void main()
{
int* Dangerous = new int; // What if there is no memory?
if (Dangerous == 0) // Now we are safe
exit(1);
set_new_handler(OutOfMemory);
int* Safe = new int;
// This is safe, if there is no memory
// OutOfMemory will be called for us
}
Inside New
Typical implementation of new
void * operator new(size_t size)
{
void *p;
if(size == 0) /* allow new(0) */
size = 2;
while (1)
{
p = __cp_malloc(size);
if (p != NULL || _new_handler == NULL)
break;
(*_new_handler)();
}
return p;
}