800 likes | 826 Views
C/ C++ Basics (III) Function, Parameters and Overloading. Berlin Chen 2003. Textbook: Walter Savitch, "Absolute C++," Addison Wesley, 2002. 1. Function ( 函數 ). Learning Objectives. Predefined Functions Those that return a value and those that don’t Programmer-defined Functions
E N D
C/C++ Basics (III)Function, Parameters and Overloading Berlin Chen 2003 Textbook: Walter Savitch, "Absolute C++," Addison Wesley, 2002
Learning Objectives • Predefined Functions • Those that return a value and those that don’t • Programmer-defined Functions • Defining, Declaring, Calling • Recursive Functions • Scope (範疇) Rules • Local variables • Global constants and global variables • Blocks, nested scopes
Introduction to Functions • Building Blocks of Programs • Terminology in Programming Languages: • Procedures, subprograms, methods • In C++: functions • I-P-O • Input – Process – Output • Basic subparts to any program • Use functions for these ‘pieces’
Predefined Functions • Libraries full of functions for our use! • Two types: • Those that return a value • Those that do not return a value • Must ‘#include’ appropriate library • e.g.: • <cmath>, <cstdlib> (Original ‘C’ libraries) • <iostream> (for cout, cin)
Using Predefined Functions • Math functions very plentiful • Found in library <cmath> • Most return a value (the ‘answer’) • Example: theRoot = sqrt(9.0); • Components:sqrt : name of library functiontheRoot : variable used to assign ‘answer’ to9.0 : argument or ‘starting input’ for function • In I-P-O: • I : 9.0 • P: ‘compute the square root’ • O: 3, which is returned & assigned to theRoot
The Function Call • Back to this assignment: theRoot = sqrt(9.0); • The expression ‘sqrt(9.0)’ is known as afunction call, or function invocation • The argument in a function call (9.0) can be aliteral, a variable, or an expression • The call itself can be part of an expression: • bonus = sqrt(sales)/10; • A function call is allowed wherever it’s legal to usean expression of the function’s return type
The Function Call #include <iostream> #include<cmath> using namespace std; int main( ) { const double COST_PER_SQ_FT = 10.50; double budget, area, lengthSide; cout << "Enter the amount budgeted for your dog house $"; cin >> budget; area = budget/COST_PER_SQ_FT; lengthSide = sqrt(area); cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(2); cout << "For a price of $" << budget << endl << "I can build you a luxurious square dog house\n"<< "that is " << lengthSide << " feet on each side.\n"; return 0; } //Computes the size of a dog house that can be purchased //given the user budget.
More Predefined Functions • #include <cmath> • fabs() // Returns absolute value of a float • #include <cstdlib> • Library contains functions like: • abs() // Returns absolute value of an int • labs() // Returns absolute value of a longint • rand() // Returns a random number of an int • srand() // No input, set seed for rand() • exit() // End program
More Math Functions • pow(x, y) • Returns x to the power y (double result) E.g. x = 3.0, y = 2.0; result = pow(x, y); cout << result; Here 9.0 is displayed since 3.02.0 = 9.0 • Notice this function receives two arguments • Generally speaking, a function can have any number of arguments, of varying data types
Predefined Void Functions • No returned value • Performs an action, but sends no ‘answer’ • When called, it’s a statement itself exit(1); // No return value, so not assigned • This call terminates program • void functions can still have arguments • All aspects same as functions that ‘returna value’ • They just don’t return a value!
The exit Function • exit(Integer_Value) • End the program immediately • Any Integer_Value can be used, but by convention, • 1 is used for a call to exit that is caused by error • 0 is used in other cases • Using function exit() must contain the following to directives #include <cstdlib> using namespace std;
Random Number Generator • Return ‘randomly chosen’ number • Used for simulations, games rand() • Takes no arguments • Returns value between 0 & RAND_MAX • Scaling • Squeezes random number into smaller rangerand() % 6 • Returns random value between 0 & 5 • Shifting rand() % 6 + 1 • Shifts range between 1 & 6 (e.g.: die roll)
Random Number Seed • Pseudorandom numbers • Calls to rand() produce given ‘sequence’of random numbers • Use ‘seed’ to alter sequence srand(seed_value); • void function • Receives one argument, the ‘seed’ • Can use any seed value, including system time:srand(time(0)); • time() returns system time as numeric value • Library <time> contains time() functions
Random Examples • Random double between 0.0 & 1.0: (RAND_MAX-rand())/(double)(RAND_MAX) • Type cast used to force double-precision division • Random int between 1 & 6: rand() % 6 + 1 • ‘%’ is modulus operator (remainder) • Random int between 10 & 20: rand() % 11 + 10 rand(),srand(), and RAND_MAX are defined in the library cstdlib. #include <cstdlib> using namespace std;
Programmer-Defined Functions • Write your own functions! • Building blocks of programs • Divide & Conquer • Readability • Re-use • Your ‘definition’ can go in either: • Same file as main() • Separate file so others can use it, too
Components of Function Use • Function Declaration or Function Prototype (函數宣告 或 函數原型) • Information for compiler • To properly interpret calls • Function Definition • Actual implementation/code for what function does • Function Call • Transfer control to function 對compiler描述函數介面,若 函數有傳回值則告訴compiler 傳回值的型態,並且告訴 compiler 函數引數 的個數和 型態 描述函數函數本身實際上如何完成計算/執行,以及傳回值。包括 2 部分: 1. function header 2. function body
Function Declaration • Also called function prototype • An ‘informational’ declaration for compiler • Tells compiler how to interpret calls • Syntax:<return_type> FnName(<formal-parameter-list>); • Example:double totalCost(int numberParameter,double priceParameter); • Placed before any calls • In declaration space of main() or an other function • Or above main() in global space 只要是合法的識別字或變數名稱即可 最好在Global Space宣告
Function Definition • Implementation of function • Just like implementing function main() • Example:double totalCost(int numberParameter,double priceParameter){constdouble TAXRATE = 0.05;double subTotal; subtotal = priceParameter * numberParameter;return (subtotal + subtotal * TAXRATE);} • Notice proper indenting function header, 與 function declaration 相似,但後面沒有分號 ; function body 當函數執行完畢傳回值事先置於一特殊位置,如暫存器或記憶體,然後呼叫的函數 就會從這個位置取回值,所以函數必須先宣告,compile才知道要讀取多少個位元組
Function Definition Placement • Placed after function main() • NOT ‘inside’ function main()! • Functions are ‘equals’; no function is ever‘part’ of another • Formal parameters (形式參數) in definition • ‘Placeholders’ for data sent in • ‘Variable name’ used to refer to data in definition • return statement • Sends data back to caller 只要是合法的識別字或變數名稱即可
Function Call • Just like calling predefined function bill = totalCost(number, price); • Recall: totalCost returns double value • Assigned to variable named ‘bill’ • Arguments here: number, price • Recall arguments can be literals, variables,expressions, or combination • In function call, arguments often called ‘actual arguments’ • Because they contain the ‘actual data’ being sent
Function Example //Computes the total cost, including 5% sales tax, //on numberPar items at a cost of pricePar each. #include <iostream> using namespace std; double totalCost(int numberParameter, double priceParameter); int main( ) { double price, bill; int number; cout << "Enter the number of items purchased: "; cin >> number; cout << "Enter the price per item $"; cin >> price; bill = totalCost(number, price); cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(2); cout << number << " items at " << "$" << price << " each.\n" << "Final bill, including tax, is $" << bill << endl; return 0; } Function declaration also called the function prototype Function definition Function call Function head double totalCost(int numberParameter, double priceParameter) { const double TAXRATE = 0.05; //5% sales tax double subtotal; subtotal = priceParameter * numberParameter; return (subtotal + subtotal*TAXRATE); } Function body
Alternative Function Declaration • Recall: Function declaration is ‘information’ for compiler • Compiler only needs to know: • Return type • Function name • Parameter list • Formal parameter names not needed: double totalCost(int numberParameter,double priceParameter); double totalCost(int, double); • Still ‘should’ put in formal parameter names • Improves readability 在函數宣告時,不一定要提供傳遞之參數的變數名稱,只要參數型態。亦即參數清單的變數名稱可有可無,而且不一定要與函數定義時實際用的變數名稱一樣。 兩種用法都可以
Parameter(參數) vs. Argument(引數) • Terms often used interchangeably • Formal parameters/arguments (形式參數/引數) • In function declaration • In function definition’s header • Actual parameters/arguments (實際參數/引數) • In function call • Technically, parameter is ‘formal’ piecewhile argument is ‘actual’ piece 接收傳遞過來 的值的變數 傳遞給函數 的值稱為實際引數或參數 C++ 標準
Functions Calling Functions • We’re already doing this! • main() IS a function! • Only requirement: • Function’s declaration(函數宣告) must appear first • Function’s definition typically elsewhere • After main()’s definition • Or in separate file • Common for functions to call many other functions • Function can even call itself: ‘Recursion’ (遞迴) 你可以在任何函數定義(function definition) 裡呼叫其他的函數 (function call),但是你不 可以在某函數定義裡再放入其他函數定義。
Parameter(參數) vs. Argument(引數) double cub(double x); int main() { ... double side=5.0; double volumn=cube(side); … … } 產生稱為side的變數,並將他設為5 5 原始值 side 傳遞值5至cube函數 產生稱為x的數,並將它 設為傳入之值 5 double cube(double x) { return x*x*x; } 5 複製的值 x
Parameter(參數) vs. Argument(引數) 在函數內宣告的變數,包括參數都是區域變數(local variables)當函數被呼叫時電腦就會配置這些變數所需的空間,當函數結束時就會釋放這些變數使用的記憶體空間 void cheers(int n); int main() { int n=150; int i=1000; int y=20; ... cheers(y); … … } void cheers(int n) { for(int i=0;i<n;i++) cout <<“cheers!”; cout <<“\n”; }; 每個函數有它自己的 變數及它自己的值 0 20 150 1000 20
Arguments in the Wrong Type/Order • Arguments in the Wrong Type • If you use an argument of the wrong type, then, in many cases, some automatic type conversion will be done by C++ • However, the results may not be what you intended • Arguments in the Wrong Order • If you confuse the order of arguments, the program will not do what you want it to do • If there is a type variation, you will get an error message when compiling • If there is no type variation, the program will probably run normally by produce an incorrect result
Boolean Return-Type Functions • Function return-type can be any valid type • Boolean return-type • Function declaration/prototype: bool appropriate(int rate); • Function definition: bool appropriate (int rate){return (((rate>=10)&&(rate<20))||(rate==0);} • Returns true or false • Function call, from some other function:if (appropriate(entered_rate)) cout << “Rate is valid\n”;
Declaring Void Functions • Similar to functions returning a value • Return type specified as ‘void’ • Example: • Function declaration/prototype: void showResults(double fDegrees, double cDegrees); • Return-type is ‘void’ • Nothing is returned 告訴compiler此函數執行完後將不回傳值 A void function also can have any number of arguments
Declaring Void Functions • Function definition: void showResults(double fDegrees, double cDegrees){ cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(1); cout << fDegrees << “ degrees fahrenheit equals \n” << cDegrees << “ degrees celsius.\n”;} • Notice: no return statement • Optional for void functions
Calling Void Functions • Same as calling predefined void functions • From some other function, like main(): showResults(degreesF, degreesC); showResults(32.5, 0.3); • Notice no assignment, since no valuereturned • Actual arguments (degreesF, degreesC) • Passed to function • Function is called to ‘do it’s job’ with thedata passed in
More on Return Statements • Transfers control back to ‘calling’ function • For return type other than void, MUST have return statement • Typically the LAST statement in functiondefinition • return statement optional for void functions • Closing “}” would implicitly return control fromvoid function 在void function函數定義裡也可以有return的敘述,只是return的後面不用再有任何的運算式或數值。 return的作用只是要來結束函數呼叫而已。 其實return可以被在放在函數定義裡的任何位置。
Function with No Arguments • It is legal, and sometimes useful, to have a function with no arguments void initializeScreen(); void initializeScreen() { cout << “\n”; } 可填入void或者什麼都沒有
Preconditions and Postconditions 函數使用之註解 • Similar to ‘I-P-O’ discussion • Comment function declaration: void showInterest(double balance, double rate);//Precondition: balance is a nonnegative account //rate is the interest rate expressed as a percentage//Postcondition: amount of interest on given balance,// at given rate … • Often called Inputs & Outputs State what is assumed to be true when the function is called Describe the effect of the function call
main(): ‘Special’ • Recall: main() IS a function • ‘Special’ in that: • One and only one function called main()will exist in a program • Who calls main()? • Operating system • Tradition holds it should have return statement • Value returned to ‘caller’ Here: operating system • Should return ‘int’ or ‘void’ You should not include a call to main in your code!
Scope (範疇)Rules In the function definition • Local variables • Declared inside body of given function • Available only within that function • Have “that” function as their scope • Can have variables with same namesdeclared in different functions • Scope is local: ‘that function is it’s scope’ • Local variables preferred • Maintain individual control over data • Need to know basis • Functions should declare whatever local dataneeded to ‘do their job’
Scope Rules #include <iostream> usingnamespace std; double estimateOfTotal(int minPeas, int maxPeas, int podCount); //Returns an estimate of the total number of peas harvested. //The formal parameter podCount is the number of pods. //The formal parameters minPeas and maxPeas are the minimum //and maximum number of peas in a pod. int main( ) { int maxCount, minCount, podCount; double averagePea, yield; cout << "Enter minimum and maximum number of peas in a pod: "; cin >> minCount >> maxCount; cout << "Enter the number of pods: "; cin >> podCount; cout << "Enter the weight of an average pea (in ounces): "; cin >> averagePea; yield = estimateOfTotal(minCount, maxCount, podCount) * averagePea; …….. } double estimateOfTotal(int minPeas, int maxPeas, int podCount) { double averagePea; averagePea = (maxPeas + minPeas)/2.0; return (podCount * averagePea); } 代表數目 代表weight
Procedural/Functional Abstraction • Write and use functions as if they were black boxes • Users need to know ‘what’ function does, not ‘how’ it does it! • Think ‘black box’ • Device you know how to use, but not it’smethod of operation • Implement functions like black box • User of function only needs: declaration • Does NOT need function definition • Called Information Hiding • Hide details of ‘how’ function does it’s job A function is like a small program!
Global Constants and Global Variables A named constant is in fact nothing but a variable that is initialized to a value and that cannot have their value changed . • Declared ‘outside’ function body • Global to all functions in that file • Declared ‘inside’ function body • Local to that function • Global declarations typical for constants: const double TAXRATE = 0.05; • Declare globally so all functions have scope • Global variables? • Possible, but SELDOM-USED • Dangerous: no control over usage! 但是scope還是 限制在同一程式裡
Global Constants and Global Variables 程式寫作注意事項 • The compiler allows wide latitude in where you place the declarations for your global named constants • To aid readability, you should place all include directives together, all global named constant variable declarations together in another group, and all function declarations (function prototypes) together • Follow standard practice to put all global named constant variables after include and using directives and before function declarations
Blocks • A block in C++ code enclosed in braces “{” “}” • Declare data inside a compound statement • Called a ‘block’ • Has ‘block-scope’ • Note: all function definitions are blocks! • This provides local ‘function-scope’ • Loop blocks: for (int ctr=0;ctr<10;ctr++){ sum+=ctr;} • Variable ctr has scope in loop body block only
Nested Scope • Same name variables declared in multiple blocks • Very legal; scope is ‘block-scope’ • No ambiguity • Each name is distinct within it’s scope void main() { int i,j; for (i=0;i<10;i++) { int varA; varA=i; cout << "varA in Loop1:"<<varA<<"\n"; for (j=0;j<i;j++) { int varA; varA=j; cout <<"varA in Loop2:"<<varA<<"\n"; } //for j }//for I }
Recursive Functions (遞迴函數) • A function definition that includes a call to itself is said to be recursive #include <iostream> using namespace std; void countDown(int n); void main() { countDown(4); } void countDown(int n) { cout << "Count dowm at level [%d] ..."<<n<<"\n"; if(n>0) countDown(n-1); cout << "Return at level [%d] "<< n <<"\n"; }
Summary 1 • Two kinds of functions: • ‘Return-a-value’ and void functions • Functions should be ‘black boxes’ • Hide ‘how’ details • Declare own local data • Function declarations should self-document • Provide pre- & post-conditions in comments • Provide all ‘caller’ needs for use
Summary 2 • Local data • Declared in function definition • Global data • Declared above function definitions • OK for constants, not for variables • Parameters/Arguments • Formal: In function declaration and definition • Placeholder for incoming data • Actual: In function call • Actual data passed to function 儘量少用global 變數
Learning Objectives • Parameters • Call-by-value (以值呼叫函數) • Call-by-reference (以參考值呼叫函數) • Mixed parameter-lists • Overloading (多載) and Default Arguments • Examples, Rules • Testing and Debugging Functions • assert Macro • Stubs, Drivers
Call-by-Value Parameters • Copy of actual argument passed • Considered ‘local variable’ inside function • If modified, only ‘local copy’ changes • Function has no access to ‘actual argument’from caller • This is the default method • Used in all examples thus far