Title: CS 192
1CS 192
- Lecture 15
- Winter 2003
- January 16, 2004
- Dr. Shafay Shamail
2Passing Values
- Ways to pass an argument to a function
- By Value
- By Address
- By Reference
- ___________________________________
- By Value
- include ltiostream.hgt
- int sqr_it(int x)
- int main()
-
- int t10
- cout ltlt sqr_it(t) ltlt ' ' ltlt t //output?
-
- int sqr_it(int x)
- x xx
- return x
-
- A copy of the value of argument t is passed to
the formal parameter x. t remains unaltered.
3Passing Pointers
- By Address
- We can use pointers to pass the address of the
actual variable - include ltiostream.hgt
- void sqr_it (int x)
- int main()
-
- int t 10
- sqr_it(t)
- cout ltlt t
- return 0
-
- void sqr_it (int x)
-
- x (x)(x) // var pointed to by x is
assigned 100 -
- Original variable whose address is passed, i, is
modified
i
100
10
5FF
j
5FF
4Passing References
- By Reference
- Eliminates the need to manipulate pointers or to
remember to pass address of argument. Not there
in C - include ltiostream.hgt
- void sqr_it(int x)
-
- int main()
-
- int t 10
- cout ltlt "Old value for t " ltlt t ltlt '\n'
- sqr_it(t) // pass address of t to sqr_it()
- cout ltlt "New value for t " ltlt t ltlt '\n'
- return 0
-
- void sqr_it(int x)
- x x // this modifies calling argument t
-
- Output 1 10
5References
- A reference is an alias for the variable.
- Simply follow the parameters type by an
ampersand in prototype e.g. int x, pronounced x
is a reference to an int - We passed the address of t to sqr_it() by
assigning another name to t, which was x. - Now the compiler automatically knows that
whenever x is encountered, we mean t, because
they are the same memory location - To pass by reference, simply call the function
with the variable name i.e. sqr_it(t) - Now mentioning the variable by its parameter name
(new alias) in the function body accesses the
original variable in the calling function
one variable, two names
10
100
5FF
t, x
6Independent References
- In addition to passing arguments by reference,
can declare a stand-alone reference variable,
called an independent reference - include ltiostream.hgt
- int main()
-
- int j, k
- int i j // independent reference
- j 10
- cout ltlt j ltlt " " ltlt i // outputs 10 10
- k 121
- i k // copies k's value into j
- cout ltlt "\n" ltlt j // outputs 121
- return 0
-
- An independent reference must be initialized when
declared. How were we initializing reference
parameters?
7Independent References
- Output of following programme?
- include ltiostream.hgt
- int main()
-
- int x 3, y
-
- cout ltlt "x " ltlt x ltlt endl ltlt "y " ltlt y ltlt
endl - y 7
- cout ltlt "x " ltlt x ltlt endl ltlt "y " ltlt y ltlt
endl -
- return 0
-
- error C2530 'y' references must be initialized
- Output if we do int y x ?
- Not a good idea to use independent references as
not necessary and inherently confusing to have
two names for same variable
8References
- Output?
- include ltiostream.hgt
- int main()
-
- int rats 101
- int rodents rats
- cout ltlt "rats " ltlt rats
- cout ltlt ", rodents " ltlt rodents ltlt endl
- rodents
- cout ltlt "rats " ltlt rats
- cout ltlt ", rodents " ltlt rodents ltlt endl
- cout ltlt "rats' address " ltlt rats
- cout ltlt ", rodents' address " ltlt rodents ltlt
endl - return 0
-
- Output rats 101, rodents 101
- rats 102, rodents 102
- rats address 006FD, rodents address
0068FD
9References
- include ltiostream.hgt
- int main()
-
- int rats 101
- int rodents rats
- cout ltlt "rats " ltlt rats
- cout ltlt ", rodents " ltlt rodents ltlt endl
- cout ltlt "rats' address " ltlt rats
- cout ltlt ", rodents' address " ltlt rodents ltlt
endl - int bunnies 50
- rodents bunnies //can we change the
reference? - cout ltlt "bunnies " ltlt bunnies
- cout ltlt ", rats " ltlt rats
- cout ltlt ", rodents " ltlt rodents ltlt endl
- cout ltlt "bunnies address " ltlt bunnies
- cout ltlt ", rodents' address " ltlt rodents ltlt
endl - return 0
-
- Output
10References
- A reference keeps referring to the same variable
to which it was initialized. You cannot change it
by assignment later on - int rats 101
- int pi rats
- int rodents pi
- int bunnies 50
- pi bunnies
- cout ltlt pi ltlt endl ltlt rodents ltlt endl ltlt rats
ltlt endl - Output 50 101 101
- Initializing rodents to pi makes it refer to
rats. Subsequently altering pi to point to
bunnies does not alter the fact that rodents
refers to rats
11Returning References from Functions
- The return type of function determines that a
reference is passed - Can use such function on LHS of assignments!
Cant do so with ordinary functions that have the
usual return types - include ltiostream.hgt
- double f()
- double val 100.0
- int main()
-
- double newval
- cout ltlt f() ltlt '\n' // display val's value
- newval f() // assign value of val to newval
- cout ltlt newval ltlt '\n' // display newval's
value - f() 99.1 // change val's value
- cout ltlt f() ltlt '\n' // display val's new
value - return 0
-
- double f()
- return val // return reference to val
-
12Returning References from Functions
- include ltiostream.hgt
- double change_it(int i) // return a reference
- double vals 1.1, 2.2, 3.3, 4.4, 5.5
- int main()
-
- int i
- cout ltlt "Here are the original values "
- for(i0 ilt5 i)
- cout ltlt valsi ltlt ' '
- cout ltlt '\n'
- change_it(1) 5298.23 // change 2nd element
- change_it(3) -98.8 // change 4th element
- cout ltlt "Here are the changed values "
- for(i0 ilt5 i)
- cout ltlt valsi ltlt ' '
- cout ltlt '\n'
- return 0
-
- double change_it(int i)
13Returning References from Functions
- If a function returns a reference to a variable
local to itself, what happens? - int f()
-
- int i10
- return i
-
- i goes out of scope when f() returns. The
behaviour of compilers is unpredictable in such
cases. Some might give warning, some might give
error. So be careful! - One way to avoid is to return reference to a
global, or to a variable that was passed to the
function from the calling function
14When to Use Reference Arguments
- We use them for two reasons
- To alter a data object in the calling function
- To speed up a programme by not passing entire
data object - Second reason important for large data objects,
such as structures and class objects - When to pass by value, by pointer, by reference?
Some guidelines - If the data object is small, such as a built-in
data type or a small structure, pass it by value - If the data object is an array, no choice but to
use a pointer - If large data object is a structure, use a
reference or pointer - If large data object is a class object, use a
reference
15Creating a Bounded Array
- To prevent array overrun
- include ltiostream.hgt
- int put(int i) // put value into the
// array - int get(int i) // obtain a value from the
// array - int vals10
- int error -1
- int main()
-
- int i
- put(0) 10 // put values into the array
- put(1) 20
- put(9) 30
- cout ltlt get(0) ltlt ' '
- cout ltlt get(1) ltlt ' '
- cout ltlt get(9) ltlt ' '
- // now, intentionally generate an error
- put(12) 1 // Out of Bounds
- return 0
- // Put a value into the array.
- int put(int i)
-
- if(igt0 ilt10)
- return valsi // return a reference to
// the ith element - else
- cout ltlt "Bounds Error!\n"
- return error // return a reference to
// error -
- //________________________________
- // Get a value from the array.
- int get(int i)
-
- if(igt0 ilt10)
- return valsi // return the value of
// the ith element - else
- cout ltlt "Bounds Error!\n"
- return error // return an error
-
16Function Overloading
- C allows you to give two or more functions the
same name. The function is said to be overloaded - You can have a function average() that computes
average of integers, another average() that
calculates average of doubles - How can we do that without ambiguity?
- Signature of a function is its list of parameters
- Overloaded functions must have different
signatures - Must differ in either the number, type, or order
of arguments i.e. different signatures - Compiler can differentiate then and calls the
correct version of the function
17Function Overloading
- Have you encountered overloading of some sort
until now in C (not necessarily function
overloading)? - The arithmetic operators. 2 3 and 2.2 3.6
- The operator is overloaded
- So, when to use overloaded functions?
- When same sort of operation is to be performed on
different data sets - Advantage Overloading functions that perform
closely related tasks can make programs more
readable and understandable - Also called function polymorphism
18Function Overloading
- include ltiostream.hgt
- void f(int i) // integer parameter
- void f(int i, int j) // two integer parameters
- void f(double k) // one double parameter
- int main()
-
- f(10) // call f(int)
- f(10, 20) // call f(int, int)
- f(12.23) // call f(double)
- return 0
-
- void f(int i)
-
- cout ltlt "In f(int), i is " ltlt i ltlt '\n'
-
- void f(int i, int j)
-
- cout ltlt "In f(int, int), i is " ltlt i
- cout ltlt ", j is " ltlt j ltlt '\n'
19Function Overloading
- Write overloaded functions, one of which averages
three double numbers, and the other two doubles - double ave(double n1, double n2)
-
- return((n1 n2)/2.0)
-
- double ave(double n1, double n2, double n3)
-
- return (n1 n2 n3)/3.0)
-
- How about int ave(double n1, double n2)...?
- Syntax error. Return type not considered by
compiler while differentiating between functions
20 ExerciseWrite three overloaded functions that
take integer, double and long respectively, and
return their absolute values
- include ltiostream.hgt
- int abs(int i)
- double abs(double d)
- long abs(long l)
- int main()
-
- cout ltlt abs(-10) ltlt "\n"
- cout ltlt abs(-11.0) ltlt "\n"
- cout ltlt abs(-9L) ltlt "\n"
- return 0
-
- int abs(int i)
-
- cout ltlt "using integer abs()\n"
- if(ilt0) return -i
- else return i
- double abs(double d)
-
- cout ltlt "using double abs()\n"
- if(dlt0.0) return -d
- else return d
-
- long abs(long l)
-
- cout ltlt "using long abs()\n"
- if(llt0) return -l
- else return l
-
21Default Function Arguments
- A default value is a value that, although not
universally applicable, is judged by the
programmer to be appropriate in a majority of
cases - A default value frees the individual from having
to attend to every small detail - For example, in Unix each text file created by
the author has read and write permissions for the
author but only read permissions for all others - In C, we can give a parameter a default value
in the function prototype. This value
automatically used when no argument corresponding
to that parameter is specified in a call to that
function
22Default Function Arguments
- Default arguments must be specified with the
first occurrence of the function name, typically
in the prototype (and where else?) - void myfunc(double num 0.0, char ch 'X')
-
- ...
-
- myfunc(198.234, 'A') // pass explicit values
- myfunc(10.1) // pass num a value, let ch default
- myfunc() // let both num and ch default
- Omitted argument must be the rightmost. If not,
also have to omit all those to its right.
Similarly for signature. - Call myfunc('A) is not correct. Also, the
signature - void myfunc(double num 0.0, char ch) is not
correct
23Default Function Arguments
- include ltiostream.hgt
- // Calculate the volume of a box
- int boxVolume(int length 1, int width 1, int
height 1) -
- int main()
-
- cout ltlt "The default box volume is "
- ltlt boxVolume() ltlt endl ltlt endl
- ltlt "The volume of a box with length 10,"
ltlt endl - ltlt "width 1 and height 1 is "
- ltlt boxVolume(10) ltlt endl ltlt endl
- ltlt "The volume of a box with length 10,"
ltlt endl - ltlt "width 5 and height 1 is "
- ltlt boxVolume(10, 5) ltlt endl ltlt endl
- ltlt "The volume of a box with length 10,"
ltlt endl - ltlt "width 5 and height 2 is "
- ltlt boxVolume(10, 5, 2)
- ltlt endl
- return 0
24Function Overloading Ambiguity
- Can have situations where compiler can not choose
which function to run. Error - Main cause is Cs automatic type conversions
attempts to convert type of argument to the type
of parameter - double mpg(double miles, double gallons)
- return (miles/gallons)
- cout ltlt mpg(45, 3) ltlt miles per gallon
- No error, as C converts 45 to 45.0 and 3 to 3.0
- int myfunc(double d)
- cout ltlt myfunc('c')//no error, conversion
applied
25Function Overloading Ambiguity
- ff(char, int)
- ff(int, int)
- ff(0, a) //matches ff(int, int) as 0 is an
exact //match of int - min(long, long)
- min(double, double)
- int i, j
- min(i, j) //error ambiguous, no best match
- foo(int, int)
- foo(double, double)
-
- foo(a, 3.14F) / error ambiguous two
bestmatches thru promotion, and no promotion
is preferred over the other /
26Function Overloading Ambiguity
- include ltiostream.hgt
- float myfunc(float i)
- double myfunc(double i)
-
- int main()
-
- // unambiguous, calls myfunc(double)
- cout ltlt myfunc(10.1) ltlt " "
-
- // ambiguous
- cout ltlt myfunc(10)
- return 0
- ...
- In C, all decimal valued constants are of type
double, unless specified to be float i.e. double
by default
27Default Arguments Ambiguity
- include ltiostream.hgt
- void ff(int i)
- void ff(long, int 0)
-
- int main()
-
- ff(2L) //matches ff(long, 0)
- ff(0, 0) //matches ff(long, int)
- ff(0) //matches ff(int)as 0 of exact type int
- ff(3.14) /error ambiguous. Can match both
functions/ - ...
- If void ff(double i) instead of ff(int i)?
- Then ff(0) is ambiguous and ff(3.14) is ok
28const Access Modifier
- Keyword const before a variable declaration makes
the value of the variable unalterable - const int change 5
- change 1 //error
- const double PI 3.14159/if pi oft-used in
programme/ - circ_area PI r r
- Have to initialize and declare a const variable
in the same line - const int students //error
- A common use of const is when we dont want
locations pointed to by pointers modified by
mistake -
29Constant Pointers
- include ltiostream.hgt
- void code(const char str)//location pointed to
by str unalterable - int main()
- code("this is a test")
- return 0
-
- void code(const char str)
-
- while(str)
- cout ltlt (char) (str1) //print a as b and
so on - str
-
- The following wont work
- void code(const char str)
-
- while(str)
30Constant Array Passing
- include ltiostream.hgt
- void display(const int num10)
- // or display(const int num)
- int main()
- int t10,i
- for(i0 ilt10 i) tii
- display(t) // pass array t to a function
- cout ltltendl
- for(i0 ilt10 i) cout ltlt ti ltlt ' '
//output? -
- // Print some numbers.
- void display( const int num10)
- int i
- for(i0 ilt10 i) (numi numi
1)//ERROR -
31Constant References
- // const references cannot be modified.
- include ltiostreamgt
- using namespace std
- void f(const int i)
-
- int main()
-
- int k 10
- f(k)
- return 0
-
- void f(const int i)
-
- i 100 // Error, can't modify a const
reference. - cout ltlt i
-
32(No Transcript)