Professional Documents
Culture Documents
A better way to do this is using a "makefile" to link together all the dependancies:
EXES = prog1
all
: $(EXES)
2. modularisation
A cpp program consists of "header" files (.h) and "cplusplus" files (.cpp). Header files contain function
specifications, e.g.
void print_hello(int nTimes);
The idea of using headers is that other programs can include them, know about the function specifications,
but not the implementation. The implementation is added during the linking; i.e. we link to the object file
containing the implementation.
3. procedural programming
Like most modern languages, c++ permits structured procedural programming. Typically, operations that
are replicated a lot in the code should be abstracted out to their own function. A function can return
nothing (void in c++), return an ordinal type (e.g. int), a pointer (e.g. int*), or an object. A function
without a return type can be called a procedure. Example function specifications:
void print_hello(int nTimes);
int random_integer(int low,int high);
float compute_fraction(int num,int total);
This is also the case when passing variables to functions. When a function is called, the current function
stack is pushed onto the program stack and a new function stack created. When the function exits, that
new function stack is destroyed and the function stack on the program stack is retrieved (by popping it). If
you make any changes to the variable value in the called function then that change is lost (passing by
value):
void increment(int num)
{
num++;
}
int main()
{
int num = 10;
increment(num);
printf("%d\n",num);
}
// still outputs 10
In this case, when increment was called a *new* value of num was created locally in the increment
function. num was passed by value and the change was forgotten in the main program. To get over this,
we pass by reference. We make one and only one change to the code:
void increment(int& num)
and now the output will be 11. The increment function did not create a new value of num, rather it created
a "reference" to the existing variable.
// & is address-of
// output is 11
In this example, in main we use &num to send the address-of the variable to the function. This address is a
pointer in the increment function. To access the data that a pointer is pointing to, you have to dereference
the pointer using *.
You can do pointer arithmetic, i.e. you can go pnum++ and you wont increment the value. Rather, you
will increment the pointer which will now point to the next address in memory. *pnum++ is needed
because you must dereference the pointer to change the value it is pointing at.
int main()
{
int num[2];
increment(num);
printf("%d %d\n",num[0],num[1]);
}
We can instantiate variables outside of this stack framework by dynamically creating them in the heap.
They exist on the heap until they are destroyed:
int* pnum = new int;
*pnum = 10;
delete pnum;
A new command allocates memory in the heap. A delete command destroys that memory. When using
new/delete you have to be careful to make sure you have the same number of each, otherwise your
program will acquire memory leaks.
You might want to allocate large data on the heap because your program will operate quicker, e.g. if you
have float[10000] then it is best to leave it on the heap rather than pushing/popping it on the stack
everytime you call a new function!
Calling this program with "prog 10 20" produces the output "2 parameters, first is 10". Note that arrays in
c++ start at zero, so we are ignoring the first value argv[0] because it is the program name.
(c) we open a file using fopen, read the contents into a buffer using fgets, and close the file using fclose:
// member variable
};
int main()
{
CStudent andrew;
andrew.DoLogicTest(10,20);
andrew.PrintLogicTestScore();
}
In this example, the "CStudent" is a class and "andrew" is an object of that class. In the main() function,
the program cannot access nLogicScore: it has to go through the public functions. You could make
nLogicScore "public", but you wouldnt want to because it would compromise the design of the class (and
external elements could alter the scores!). This example demonstrates data hiding and encapsulation.
Constructors and Destructors are crucial. If we have elements on the heap for an object, then (a) we need
to allocate the memory for them in the constructor (or somewhere in one of the members if needbe), (b)
we absolutely need to deallocate the memory in the destructor (because this is your last chance, after this
the pointers will get thrown away).
8. advanced oop
A very attractive property of object-oriented programming is that you can create classes that inherit
functionality from other (base) classes. This is called inheritance. For classes/objects we can also
implement basic operators, like ==, to make them easier to use. This is called operator overloading.
class CPerson
{
public:
CPerson();
~CPerson();
void ComputeAge(char* szDateOfBirth);
int GetAge();
private:
int age;
};
class CStudent : public CPerson
{
public:
CStudent();
~CStudent();
void DoLogicTest(int answera,int answerb);
void PrintLogicTestScore();
private:
int nLogicScore;
// member variable
};
int main()
{
CStudent andrew;
andrew.DoLogicTest(10 20);
andrew.PrintLogicTestScore();
andrew.ComputeAge("01 April 1985");
printf("andrew is %d years old\n",andrew.GetAge());
}
In this example, the "CStudent" class inherits from "CPerson". This means, that objects of class CStudent
inherit all the functionality from the CPerson class (without replicating the code!). This is very useful if
you can design abstract classes which are reused a lot: it can save you a lot of time.
We perform operator overloading by adding:
9. error handing
c++ comes with a number of techniques for error handling and preventing bugs:
(a) a c++ program returns 0 if it was successful, !0 otherwise,
(b) you can use assertions to check that incoming parameters to your functions are within allowed ranges.
It is estimated that 10% of all lines of code in MS Windows are assertions! (Source: Professor Sir Tony
Hoare, Microsoft Research).
(c) you get try { function } catch(...) { error procedure } error handing to catch errors as they occur.
Andrew Graves
November 2004.