object-oriented programming in c++ lecture 3 functions header files
TRANSCRIPT
Object-Oriented Programming in C++
Lecture 3
Functions
Header Files
IntroductionLast lecture we
– reviewed the concept of classes– discussed their representation using UML
class diagrams– implemented and used a simple C++ class– introduced C++ structures and enumeration
types
This lecture we will look at C++– functions– header files
C++ Functions
• we have already written some C++ functions in the Account class
class Account {//….. // return the account's balance double getBalance(){ return balance;}
// add money to the account void deposit(double amount) { balance += amount; }// …..
};
C++ Functions• C++ functions are similar to those in Java, C, C#
– also known as methods, subroutines, or procedures
• general form:type function_name (parameter list) {
statements;
return statement;
}
• in C local variables must be declared at the beginning the function
• in C++ they can be declared anywhere in the function• unlike in Java and C#, functions don't need to belong
to a class
A function to add two numbers
#include <iostream>using namespace std;
int addNums(int x, int y) { return x + y;}
int main() { int a = 3; int b = 5; int answer = addNums(a, b); cout << a << " + " << b << " = " << answer << endl; cout << "7 + 6 = " << addNums(7, 6) << endl;}
Functions • in C++, C, Java, and C#, the return statement returns control to the
calling function• the returned value must have the same type as the function
int addNums(int x, int y) {
return x + y;
}• a function that does not return a value has type void
– the return statement may be omitted
void error_mess (int err_no) {
cout << "Error " << err_no << " has occurred " << endl;
}• calling the function:
if (slope < 0)
error_mess(5);
}
Overloading functions• consider the addNums function
int addNums(int x, int y) {
return x + y;
}
• it takes two integers as parameters–and returns an int
• what if we wanted to add two doubles?
• three integers?
• we need to write more functions
• we are allowed to give them the same name–as long as they can be distinguished by their parameter lists–this is function overloading
• C does not allow overloading
Overloads of addNum
int addNums(int x, int y) {return x + y;
}double addNums(double x, double y) {
return x + y;}int addNums(int x, int y, int z) {
return x + y + z;}
• which function will be called by:answer = addNums(3.1f, 4.5f); ?answer = addNums(3, 4.5); ?
Overloading functions• selection of the correct function overload occurs
at compile time
• the compiler will first try to find an exact match to the parameter list
• it then applies any possible type conversions– int or float to double
• if the compiler cannot choose it will give an erroranswer = addNums(3, 4.5);error C2666: 'addNums' : 2 overloads have similar conversionstest.cpp(55): could be 'double addNums(double,double)'test.cpp(51): or 'int addNums(int,int)'
Overloading functions• function overloads that have the same parameter list but differ
only in the return type are not allowed• how would the compiler know which overload to call?
double addNums(double x, double y) { return x + y;}int addNums(double x, double y) { return (int)(x+y+0.5);}// …
int answer = addNums(3.2, 5.6); // ????
error C2556: 'int addNums(double,double)' : overloaded function differs only by return type from 'double addNums(double,double)'
Default arguments
• we can sometimes avoid writing multiple overloads by providing default values in the function declarationint addNums(int x, int y, int z = 0) {
return x + y + z;}
• can be called by bothanswer = addNums(5, 2);answer = addNums(3, 1, 8);
• in the first call, z is assigned the value 0• parameters with default values must appear at the
end of the parameter list–why?
Overloaded operators
• in practice, we probably wouldn't write an addNums function
• we would use the '+' operator instead• '+' is already overloaded to work with all
integral and floating point types• it also works with strings
– concatenationstring s1 = "Cathy ";string s2 = "French";string s3 = s1 + s2;
s3 contains "Cathy French"
Inline expansion• Function calls are expensive• The inline keyword requests that the
compiler replace every call to this function with the code inside the function.– the compiler can ignore this request inline int addNums(int x, int y) { return x + y;}
• the function callint answer = addNums(a, b);
might be expanded by the compiler to int answer = a + b;
Inline expansion
• advantage of inline expansion– avoids the overhead of function call and return
• particularly useful for short functions
• disadvantages– compiled program can take up more room in
memory• because function code is repeated for every function
call
– CPU can't take advantage of instruction caching
What is the output?
#include <iostream>using namespace std;
int main() { function1(true); function2(true);}
void function2(bool val) { cout << "This is function 2" << endl; if (val) function1(!val);}
void function1(bool val) { cout << "This is function 1" << endl; if (val) function2(!val);}
Output
1>------ Build started: Project: Express Examples, Configuration: Debug Win32 ------1> Functions.cpp1>g:\c++\express examples\express examples\functions.cpp(5): error C3861: 'function1': identifier not found1>g:\c++\express examples\express examples\functions.cpp(6): error C3861: 'function2': identifier not found1>g:\c++\express examples\express examples\functions.cpp(12): error C3861: 'function1': identifier not found1> Generating Code...====Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ====
What went wrong?
• In C++ a function must be declared before it is used (called)
• so that the compiler can check that the correct parameters and return types are being used
• can we rearrange the program to make it compile?
Prototypes
• in some cases (but not this one) it is possible to carefully order the functions – so each is defined before it is called
• can get messy if a program has lots of functions– especially if they are split up over several files
• a better solution is to use prototypes• a function prototype or declaration gives the name, number
and type of arguments, and return type of the functionvoid function1(bool val); void function2(bool val);
• no method body• the argument name (val ) is optional• but it helps document the function
Using a prototype#include <iostream>using namespace std;void function1(bool val);void function2(bool val);
int main() { function1(true); function2(true);}
void function2(bool val) { cout << "This is function 2" << endl; if (val) function1(!val);}
void function1(bool val) { cout << "This is function 1" << endl; if (val) function2(!val);}
function prototypes or declarations
function definitions
Header files• when developing larger programs, it is useful to put the
prototypes in a separate header file– suffix .h, for example MyFunctions.h
• any program file that uses these functions can include the header file#include “MyFunctions.h”
• this enables the compiler to check the parameters and return type of any functions called are correct– without needing to access the function definitions
• header files can also contain constants, enums, structures and class declarations
• the use of header files allows the same declarations to be used in many .cpp files
Where are the header files?
• header files for C library functions are in a directory called include– on my system, it is in C:\Program Files\Microsoft Visual
Studio 9.0\VC\include
• the path to this directory can be set in Visual Studio– or by setting the Windows Environment variable
INCLUDE• in UNIX systems, header files are usually in /usr/include• the preprocessor searches in the include directories for
header files specified between angled brackets#include <iostream>
• tell the preprocessor to look in the current directory first by putting the header file name in quotes#include “Account.h”
Multiple-source compilation• each source .cpp file is compiled separately• the compiler requires declarations for all
functions, classes, structures, constants the file referred to
• need to #include the appropriate headers – preprocessor copies their contents into the file
• output of compilation is an object file– includes a symbol table of references to functions
whose code is not available– could be library functions, or functions defined in
other source files
Multiple-source compilation
• the linker then combines the object files together into a single executable
• resolves the external references in the symbol table
• the linker looks for this external code in– the executable directory path specified for the
project– the paths set for executable and library files
Guarding against multiple inclusions
• functions can be declared multiple times in the same source file– prototypes repeated
• but defined only once– method body
• structures, enums and classes can be declared only once
• it's easy to include the a header file twice in the same source file
• guard against this by using conditional definition or pragma
A header file: structures.h#ifndef STRUCTURES_H#define STRUCTURES_Hstruct Point3D { float x; float y; float z;};enum colour { RED, ORANGE, YELLOW,GREEN,BLUE,VIOLET};#endifif STRUCTURES_H is not yet defined, define it as everything up to the #endifotherwise ignore everything to the #endif
#pragma once
• an alternative is to use #pragma once• specifies that the header file should be
opened only once by the preprocessor
• if the header is included twice in the same source file, it won't be opened and copied in the second time
• in our first version of Account, we put the entire class definition in the header file
• doing so defines all the functions inline by default
• this is suitable for short functions likedouble getBalance(){ return balance;}
• but not longer functions like withdraw• we could define these functions in a separate
file, account.cpp• need to include the class name in the definition
Header files for classes
Account.h#ifndef ACCOUNT_H#define ACCOUNT_H
class Account {private:
double balance; double interestRate;
public: Account(double initialBalance, double rate); double getBalance();void deposit(double amount); void withdraw(double amount); void addInterest();
};#endif
account.cpp#include "account.h"
Account::Account(double initialBalance, double rate) :balance(initialBalance), interestRate(rate) { } double Account::getBalance(){return balance;}
void Account::deposit(double amount) { balance += amount;}void Account::withdraw(double amount) { // implement this method yourself}void Account::addInterest() { balance *= (1 + interestRate/100.0); }
SummaryIn this lecture we have looked at C++•functions
– syntax, overloading, default arguments, inline expansion
•header files– need for prototypes, compiling multiple source files
Next lecture we will•continue looking at functions•and introduce reference types