SDSU 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

  1. References
  2. Functions
    1. Default Parameters
    2. Overloading Functions
    3. Inline Functions
    4. Template (Generic) Functions
    5. Scope
    6. Pointers to Functions
    7. Ellipses - Variable number of Arguments
    8. New - Delete

References


C++ Primer, Lippman. Sections 3.2, 3.5, 3.6, 3.7, 3.8, 3.9, 3.11, chapter 4

Functions


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

Default Parameters

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

Overloading Functions

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	

}

Inline Functions

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 
}

Template (Generic) Functions

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++

Scope

C++ Only

:: - use global variable
#include <iostream.h>

int where = 10;

main()
{

	int where = 5;

	cout 	<< ::where 	// prints 10

		<< "\n" 

		<< where 	// prints 5

		<< "\n";
}


Pointers to Functions

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

}

Ellipses - Variable number of Arguments

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

New - Delete

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