You are on page 1of 19

1

Mekelle University Faculty of Business & Economics

Computer Science Department

ICT122: Object-Oriented Programming

Handout 1 – Introduction to C++ and Classes

Handout Overview

This handout introduces the concept of object-oriented programming. The principle


differences between conventional procedural programming languages and object-
oriented programming languages are described. The new input/output and comment
statements provided by C++ are introduced. Finally the concept of a C++ class is
described in detail.

1. Course Overview

One of the reasons that C++ has become so widely used is that it enhances the C
programming language to introduce a number of powerful object-oriented features,
whilst preserving the features of C that made it such a popular language for so long.
The most important of these new features are the ideas of classes and inheritance.
Classes will be discussed later in this handout and inheritance will be dealt with in
Handout 2.

In addition to the new object-oriented programming language features, C++ provides


an interesting and potentially very useful new feature known as operator overloading,
which will be discussed in Handout 3.

In Handout 4 we will look at the idea of templates, which is another new feature of
C++ that enables programmers to write code that is independent of the data types it
operates on, thus making more effective reuse of code possible.

Finally in Handout 5 the object-oriented design process will be examined in some


detail, through the use of a realistic design case study.

To begin with, in this handout we will introduce the concept of object-oriented


programming, briefly discuss the object-oriented view of the world and introduce
some object-oriented design concepts. These are the concepts that underly many of
the topics in this course.
2

2. Object-Oriented Programming

2.1. Procedural vs. Object-Oriented Programs

Historically, most programming languages have been procedural languages. This


means that programs work by executing a sequence of instructions provided by
the programmer. Examples of procedural languages include BASIC, Pascal and
C. More recently, another way of programming has gained in popularity, known
as object-oriented programming. Object-oriented programming languages allow
the programmer to break down the problem into objects: self-contained entities
consisting of both data and operations on the data.

C++ is an object-oriented programming language, but since C++ is derived from


C, it also contains many procedural language features too. Other examples of
object-oriented programming languages are Java and Smalltalk. The concept of
object-oriented programming will become clearer as you learn more about C++
and its programming features.

2.2. The Benefits of Object-Oriented Programming

In object-oriented programming data plays a leading role. Data that is related is


grouped together with the operations that process the data. This enables object-
oriented programs to more accurately model the structure of the real world.
Because of this, many programmers find the object-oriented approach to problem
solving more intuitive and easier to reason with.

Object-oriented languages have three main features that distinguish them from
other types of programming language:
• Encapsulation
• Inheritance
• Polymorphism/dynamic binding

Encapsulation means separating the logical properties of a data structure (what it


does) from its implementation details (how it does it). Encapsulation is also
sometimes referred to as information hiding. It is a common technique that the
human mind uses to tackle complex problems: break the problem down into a
number of smaller, simpler, well-defined sub-problems and solve each
individually. By specifying the required inputs and outputs of a sub problem we
are abstracting it away from the main problem. An example of the way in which
people use abstraction is driving a car – when we drive a car we do not think
about how the engine is working (the implementation), we only think about how
we manipulate the steering wheel, pedals and gear stick (the public interface). If
the program is designed well, encapsulation can lead to more secure and reliable
software.
3

Inheritance is a mechanism by which object-oriented languages allow objects to


reuse all or part of the code in another object or objects. Inheritance can also lead
to more reliable and easily understandable software that better models the
structure of the real-world problem, and will be dealt with in depth in Handout 2.

The term polymorphism literally means “taking many different forms”. This
important concept will be discussed in Handout 2 (Inheritance) and also Handout
4 (Templates). Related to polymorphism is the concept of dynamic binding. C++
provides dynamic binding capabilities by the use of virtual functions which will
be discussed in Handout 2.

2.3. Code Reuse

Many of the features of object-oriented programming languages are aimed at


allowing the programmer to reuse existing code more effectively. Code reuse
simply means to somehow reuse an existing piece of code to perform a new
operation, rather than writing an entirely new piece of code every time. The
concept of code reuse is not new: ever since programming began programmers
have tried to reuse code. For example, functions in C allow code reuse. Code
reuse is generally considered to be a good thing in computer programming
because it reduces the amount of work involved in writing programs, allowing
faster code development. Also, programs that reuse code are easier tom
understand, debug and modify. One of the advantages of object-oriented
programming languages is that they generally allow greater code reuse than
conventional programming languages.

2.4. The Object-Oriented View of the World

In object-oriented programming a program is viewed as a system of interacting


objects. Each of these objects represents a thing in the real world. The objects are
related and interact with each other by sending messages to each other and
eacting to these messages. The role of the object-oriented programmer is to
define the objects, their relationships, the messages that they send and how they
respond to these messages.

Let us illustrate this with an example. Suppose you are required to write a
battlefield simulation program. The battlefield should consist of a number of
battefield units. Battelfield units can be either soldiers or tanks. Tanks and
soldiers both have weapons, although both can have different types of weapon,
and can even carry more than one type of weapon each. When a tank or soldier
fires a weapon, the program should be able to simulate the trajectory of the
bullet/missile and determine the damage it has caused.
4

How would we approach the design of this program from an object-oriented


perspective? Remember that our final program must consist of objects that
represent things in the real world, and that these objects have relationships
between them. One possible object-oriented solution is given in Figure 1.

Figure 1 – Objects and relationships for a battlefield simulation program

Each of the ellipses represents an object and the lines represent relationships.
You can see that we have objects to represent battlefield units, tanks, soldiers and
weapons. Also there is an object called trajectory, which is reponsible for
calculating the trajectory of projectiles fired by weapons and determining the
damage done. Clearly there is a relationship between a battlefield unit and a tank,
because a tank is a type of battelfield unit. Also, there is a clear relationship
between a tank and a weapon, because tanks have weapons. Finally, there is a
relationship between weapons and the trajectory object, since when a weapon is
fired we must calculate the trajectory of the projectile. Although all of these are
relationships, they are not the same type of relationship. We can say that a soldier
is-a battlefield unit, but we cannot say that a weapon is-a soldier. Similarly we
can say that a tank has-a weapon but we cannot say that a battlefield unit has-a
soldier. We say that the weapon object uses the trajectory object to calculate the
damage done by the weapon.

It is important to understand the difference between these types of relationship,


as we will come back to them later in the course. The process of reading a
program specification like the one given above and producing a set of objects and
relationships is one that comes with exeprience, but some guidance will be given
when the subject of objct-oriented design is covered in more depth in Handout 5.

3. Extra Features of C++

Before we start to discuss the object-oriented features of C++, we will deal with a
couple of new simple statements introduced in C++. The first new addition we will
consider is the new input/output statements it provides.

3.1. Input/Output Statements


5

Whereas the C programming language provided the built-in functions scanf and
printf to input information from the user, or output information to the user,
C++ provides an alternative mechanism. In C++ you can still use scanf and
printf, but you can also use the commands cin and cout. For example, the
following program will print a message to the screen, then read in two int values
from the user:

#include <iostream.h>

main()
{
int n1, n2;
cout << “Enter 2 numbers:” << endl;
cin >> n1 >> n2;
}

First of all, notice that the arrow symbols (<< and >>) are pointing in different
directions for the cin and cout statements. Also, note that you can have more
than one of these symbols in each statement: the cin statement has two >>
symbols, which means that it reads in two numbers one after the other. Similarly
the cout statement prints the piece of text “Enter 2 numbers:” followed by the
endl symbol. The endl symbol just starts a new line on the screen.

The #include <iostream.h> statement must be included at the start of the


program if you want to use input & output statements in C++. This is the standard
way of including definitions from a predefined library of routines. C++ has many
such libraries, and we will use some different ones later on.

You may wonder why C++ provides the cin and cout statements when the
scanf and printf statements work perfectly well. The main reason for this is
related to the idea of operator overloading, which we will discuss in Handout 3.

3.2. File I/O

File I/O statements are performed in a similar way to the standard I/O statements
just described. Consider the following program:

#include <fstream.h>
int x;
ifstream f;
ofstream g;
f.open(“inputfile”);
g.open(“outputfile”);
f >> x;
g << x;
f.close();
g.close();
6

This program reads in a single integer from an input file called “inputfile”, and
writes the same integer to an output file called “outputfile”. The actual statements
that do the reading and writing,

f >> x;
g << x;

are similar to the cin and cout statements. The important differences to note here
are that the input and output files must be opened before use and closed after use.
Also, ifstream or ofstream objects must be declared for input and output files
respectively.

3.3. Comment Statements

C++ also provides an alternative way of entering comments statements into your
program. You can still use the C language comments (i.e. /* ...*/), but in
addition you can add comments by typing a double-slash (‘//’). This causes the
compiler to ignore the remainder of the line after the double-slash, e.g.

// declare program variables


int a = 3, b;

4. Objects in C++

4.1. Structures

Before discussing how to define objects in C++, we will briefly recap on the
structure advanced data type in C. Structure types are used for storing a
collection of values of different types. Each value in a structure type is called a
member of the structure. The following is an example of a structure type to store
information about students:

enum RegExt {Regular, Extension};


struct Student {
char *name;
char *fathersName;
RegExt programme;
float gpa;
};

Here we have defined two new data types: an enumeration type called RegExt,
and a structure type (struct) called Student. Variables declared to be of the
Student type will consist of 4 values. The first two members (name and
fathersName) are both pointers to char types. The other two members are of
types RegExt and float respectively. Notice that the format for declarations of
7

structure members is the same as that for ordinary variable declarations, they just
appear within a struct declaration. To illustrate the syntax for accessing or
assigning to members of structure variables, consider the following code:

Student s;
s.name = “Teklay”;
s.fathersName = “Zenawi”;
s.programme = Regular;
s.gpa = 3.2;

Here we first declare a variable s of type Student. Next all of the members of s
are initialised by typing a full stop (‘.’) after the variable name followed by the
member identifier. When a character string (e.g. “Teklay”) is assigned to a
variable of type char* the C++ compiler will automatically allocate enough
memory to store the sequence of characters.

4.2. C++ Classes

Remember that in object-oriented programming, objects consist of a set of related


data, together with the operations that process that data. You can define objects in
C++ using classes. A class is a similar concept to a structure in C, except that as
well as containing a set of data members, it can also contain member functions for
operating on that data. This is an important difference: in traditional procedural
programming there was a clear division between data and the operations that
process the data; in object-oriented programming this division is not so clear.
Rather than having separate data and functions, we instead have objects, which
consist of data together with operations on that data. In C++, we call these objects
classes. You can think of a class as a special kind of data type. When we ‘declare
a variable’ of this data type, it is called an object.

4.3. Classes and Abstract Data Types

A class in C++ is actually an example of an abstract data type (ADT). An ADT is


a user defined data type whose properties are specified independently of any
particular implementation. That is, the programmer specifies the inputs and
outputs of the data type, but hides the details of the implementation from the rest
of the program. This means that (s)he can change this implementation at a later
date without changing the way the rest of the program interacts with the ADT. Use
of ADTs has been common in procedural languages for many years, but object-
oriented languages like C++ provide a formal mechanism for implementing ADTs
and enforcing the hiding of implementation details.

For further discussion of the idea of data abstraction in relation to C++ classes,
see Dale, Weams & Headington (p838) or Cohoon & Davidson (p401).
8

5. Example 1 – Solving Quadratic Equations

We will first illustrate the concept of a class by means of a simple example. The
following code defines a class for storing information about and solving quadratic
equations.

”quadratic.cpp”

#include <iostream.h>

class quadratic {
// data members
public:
float a, b, c;
// member functions
void solve () {
float root1, root2;
float x = b * b - 4 * a * c;
if (x < 0)
cout << "Roots complex" << endl;
else {
root1 = (-b + x) / (2 * a);
root2 = (-b - x) / (2 * a);
cout << "Roots = " << root1 << ", " << root2 <<
endl;
}
}
};
int main () {
quadratic q;
cout << "Enter a b c:" << endl;
cin >> q.a >> q.b >> q.c;
q.solve();
}

Examine the code given above. Look first at the way the quadratic class is
defined. After the C++ keyword class and the class identifier (i.e. it’s name) there
are some data member definitions. The quadratic class has 3 float data
members, called a, b and c. These are like ordinary variable declarations, except that
they are preceded by the C++ keyword public. Data members in C++ classes can
be public, private or protected. Public data members are accessible to code
outside of the class, whereas private data members can be accessed only by member
functions of the class. We will see later what is meant by a protected data member.

After the data members have been specified, the member functions are defined. In the
quadratic class there is a single member function called solve. Note that this
member function is also specified as public. This means that this function can be
9

called by code outside of the class. In the main program an object q of the class
quadratic is declared. This declaration appears to be the same as a normal
variable declaration. However, when we wish to perform an operation on the class,
we see the difference: the operations are also members of the class so the object name
has to be specified along with the operation required. e.g. q.solve() will print out
the solutions to the quadratic equation contained in object q. Try entering and running
this code and make sure that you understand how it works.

6. Example 2 – A Student Database

Now we will look at a more complex example. The following code defines a class for
storing student data. It is the convention when defining C++ classes to separate the
class definitions from the member function bodies, to improve program clarity. Class
definitions are normally held in header files with the suffix “.h”, and function bodies
in C++ source files with the suffix “.cpp”. Using the Quincy editor you can create
C++ source files (i.e. “.cpp” files) by selecting the C++ Source File option after
selecting New from the File menu. To create a header file just select Header File as
the file type. Because this example involves more than one C++ source file, we must
create a Quincy project to contain the files. A project is just a collection of files that
are part of the same program. To create a new project choose New from the File
menu, and then choose the Project option when asked to select the file type. Add the
files to the project by selecting Insert File(s) from the Project menu.

The definition for the student class is given in “student.h”, and the member function
bodies are given in “student.cpp”. The main program is in “process.cpp”.

“process.cpp”

#include <iostream.h>
#include "student.h"

main ()
{
Student s;
s.Print();
Student s2 ("Rahel", "Gezahegn", Extension, 3.7);
s2.Print();

s.setName ("Teklay", "Zenawi");


s.setProg (Regular);
s.setGPA (3.2);
s.Print();
}

“student.h”

enum RegExt {Regular, Extension};


10

class Student {
//data members
private:
char *_name;
char *_fathersName;
RegExt _programme;
float _gpa;

//member functions
public:
Student();
Student(char *n, char *fn, RegExt p, float a);
~Student();
void setName(char *n, char *fn);
void setProg(RegExt p);
void setGPA(float a);
void Print() const;
};

“student.cpp”

#include <iostream.h>
#include "student.h"

Student::Student() {
_name = "";
_fathersName = "";
_programme = Regular;
_gpa = 0.0;
}

Student::Student(char *n, char *fn, RegExt p, float a) {


_name = n;
_fathersName = fn;
_programme = p;
_gpa = a;
}

Student::~Student() {
cout << "Student Destructor" << endl;
}

void Student::setName (char *n, char *fn) {


_name = n;
_fathersName = fn;
}
void Student::setProg (RegExt p) {
_programme = p;
}

void Student::setGPA (float a) {


_gpa = a;
}
11

void Student::Print () const {


cout << "Name: " << _name
<< " " << _fathersName << endl;
if (_programme == Regular)
cout << "Regular Programme\n";
else
cout << "Extension Programme\n";
cout << "GPA = " << _gpa << endl << endl;
}

First look at the Student class definition in “student.h”. Note in this example that
the data member definitions are preceded by the C++ keyword private. This
means that the data members cannot be accessed by code outside of the class itself.
Another way of putting this is to say that this information is hidden from code outside
of the class. The public, private and protected access levels are the mechanism that
C++ uses to achieve the concept of encapsulation, or information hiding. (See
Section 1.1.) Typically the logical properties of a class will be defined by the public
members (i.e. the public interface), whereas the implementation details will be either
private or protected.

Notice also that the names of the data members all begin with the underscore
character (‘_’). This is just convention. Many C++ programmers like to start data
member names with the underscore to make it easier to distinguish between class data
members and ordinary variables. You do not have to do this though – in the
quadratic example the data member names did not start with underscores.

After the data members have been specified, the member functions are defined. The
member functions are all specified as public so they can be called by code outside
of the class. Because the data members are all private we need to define public
member functions so that the program can modify the values of these data members.
You do not have to do it this way: in the previous example all data members were
public and could be modified from anywhere in the program, but using information
hiding like this allows the class to retain control over how its data is changed. The
class can validate any changes requested by the program. Note that it is also possible
to have private member functions – they can only be called by other member
functions. The collection of public data members and public member functions can be
seen as the public interface to the class.

In the “student.h” file only the member function prototypes are given. It is possible to
include the function bodies inside the class definition as in the quadratic equation
example, but generally it improves program readability if you specify the function
bodies elsewhere. In our example we have included them in the “student.cpp” file.
Notice how we use the scope operator ‘::’ to indicate that the function body being
defined is a member function of a particular class.

Notice also the const keyword after the void Print() function, both in the
prototype and the function body. If you specify a member function as const it will
12

not be able to change the values of any of the data members of the class. Note that in
most cases it is not necessary to declare a member function as const – in the quadratic
equation example the solve function does not change the values of any data
members but we did not define it as a const function. However, it is good
programming practice: if there was a bug in the Print function that meant that it did
accidentally change the value of a data member it would be reported as a compilation
error. Therefore using const member functions where appropriate can help you to
debug your programs.

7. Constructors and Destructors

As C++ classes often contain a number of different data members; it is often desirable
to perform some initialisation on them when an object of the class is first declared.
This is possible by using constructors. Constructors are special member functions
which are normally only called when an object of the class is declared. The function
name of a constructor is the same as the class name. In the Student class there are
two constructors, defined by the following function prototypes in “student.h”:
Student();
Student(char *n, char *fn, RegExt p, float a);
The corresponding function bodies are specified in “student.cpp”. Precisely which
constructor is called when an object is declared depends on the number and type of
arguments provided. For example, the declaration
Student s;
will cause the first constructor to be executed, whereas the declaration
Student s2 ("Rahel", "Gezahegn", Extension, 3.7);
will cause the second constructor to be executed. Notice also that constructor
functions have no return type.

Similarly, it is also possible to define a destructor. A destructor is a member function


that is only called when the program has finished with an object. Class destructors
also have no return type, and have the same name as the class but are preceded by the
‘~’ symbol. For many classes you may not need to define a destructor, but they can be
useful for more complex classes. If no constructor or destructor is defined, then the
default will be an empty function.

8. Static Class Members

In C++ classes, all objects of a particular class have their own copies of the data
members. For instance, in the student example, Rahel Gezahegn and Teklay Zenawi
have different GPAs, programmes and names. However, sometimes it is necessary for
all objects of a class to have access to the same variable. In C++ we can do this by
making a data member static. If you define a data member of a class as static then
only one copy of it is stored irrespective of how many objects of the class are created.
13

All objects access this same copy. Static data members must be initialised at the
beginning of the program using the class scope operator ‘::’.

Suppose we wish to store a count of the total number of students in the database.
Every time a new student object is created we want to add one to this count, and
every time a student object is destroyed we want to subtract one. We accomplish this
in the modified code below by defining an extra public static data member called
_count in the Student class. This is incremented in the Student constructors,
and decremented in the Student destructor.

“process.cpp”

#include <iostream.h>
#include "student.h"

// initialise static data member


int Student::_count = 0;

main () {
Student s;
s.Print();
Student s2 ("Rahel", "Gezahegn", Extension, 3.7);
s2.Print();
cout << “Number of students = “ << s.Count() << endl;
s.setName ("Teklay", "Zenawi");
s.setProg (Regular);
s.setGPA (3.2);
s.Print();
}

“student.h”

enum RegExt {Regular, Extension};

class Student {
//data members
private:
char *_name;
char *_fathersName;
RegExt _programme;
float _gpa;
static int _count;

//member functions
public:
Student();
Student(char *n, char *fn, RegExt p, float a);
~Student();
void setName(char *n, char *fn);
void setProg(RegExt p);
void setGPA(float a);
void Print() const;
14

int Count() {return _count;}


};

”student.cpp” (modified parts only)

Student::Student() {
_name = "";
_fathersName = "";
_programme = Regular;
_gpa = 0.0;
_count += 1;
}
Student::Student(char *n, char *fn, RegExt p, float a) {
_name = n;
_fathersName = fn;
_programme = p;
_gpa = a;
_count += 1;
}

Student::~Student() {
cout << "Student Destructor" << endl;
_count -= 1;
}

8.1. Static Member Functions

The above example will work fine in most cases. However, there is a slight
problem. The value of the private _count static data member is being accessed
through a public member function Count(). The only way to access a member
function of a class is through an object of that class. But what happens if there
are no objects of the class to access the static data member through? In other
words, what happens if we want to access the value of _count before any
Student objects have been declared? Currently it is not possible. We can
rectify this situation by making the Count() function a static member function.
Static member functions of a class can be called even when there are no objects
of the class to call it through. The following modified code declares Count() as a
static member function and illustrates how to make a call to it when there are no
objects declared.

“process.cpp” (modified parts in bold)

#include <iostream.h>
#include "student.h"

// initialise static data member


int Student::_count = 0;
15

main () {
cout << “Number of students = “ << Student::Count() << endl;
Student s;
s.Print();
Student s2 ("Rahel", "Gezahegn", Extension, 3.7);
s2.Print();
cout << “Number of students = “ << Student::Count() << endl;
s.setName ("Teklay", "Zenawi");
s.setProg (Regular);
s.setGPA (3.2);
s.Print();
}

“student.h” (modification in bold)

enum RegExt {Regular, Extension};

class Student {
//data members
private:
char *_name;
char *_fathersName;
RegExt _programme;
float _gpa;
static int _count;

//member functions
public:
Student();
Student(char *n, char *fn, RegExt p, float a);
~Student();
void setName(char *n, char *fn);
void setProg(RegExt p);
void setGPA(float a);
void Print() const;
static int Count() {return _count;}
};

8.2. Inspectors, Mutators and Facilitators

Class member functions are generally divided into 3 categories, based upon their
function. This categorisation is just object-orintedn programming terminology –
the functions are not any different as far as the C++ compiler is concerned.

The first category is inspector functions. Inspector functions simply return the
value of a data member of the class. For example, the Count() function in the
student example is an inspector function. It is common to have public inspector
functions for private or protected data members.

The second category is mutator functions. Mutator functions change or set the
value of a data member. The setName, setProg and setGPA functions are
16

all mutator functions. Again, it is common to have public mutator functions for
private or protected data members. Mutator functions may also perform some
validation on the data to be assigned into the data member(s), to maintain the
integrity of the class data.

Finally, facilitator functions cause an object to perform some action or service.


The Print() function in the Student class is an example of a facilitator
function.
17

Summary of Key Points

• In the past, most programming languages were procedural (i.e. they consist of
a sequence of statements executed one after the other).
• In object-oriented languages programs consist of a number of objects that
consist of both data and operations on that data.
• C++ is a language that extends the procedural language C by introducing a
number of object-oriented features. As such it is a mixture of procedural and
object-oriented languages. It is not a pure object-oriented language.
• Many features of object-oriented languages are aimed at allowing more
effective code reuse
• Object-oriented languages have three main features: encapsulation,
inheritance and polymorphism/dynamic binding.
• Encapsulation means separating the logical properties of an object (i.e. what it
does) from its implementation details (i.e. how it does it). Encapsulation is
also known as information hiding.
• Inheritance is a mechanism that allows programmers to reuse code, and leads
to programs that better model the structure of the real world problem.
• Polymorphism means “taking many different forms”. implements
polymorphism in two ways: through the use of virtual functions and
templates.
• Dynamic binding is a related concept to polymorphism, as is implement in
C++ through the use of virtual functions.
• Input/output in C++ can be performed using the cin and cout statements.
• Comments in C++ can be written using the double-backslash, i.e. //
• C++ classes consist of a set of related data (data members) together with
operations on that data (member functions).
• A class is like a data type. When we ‘declare a variable’ of a class, it is called
an object.
• Classes can be thought of as a formal mechanism for writing abstract data
types (ADTs).
• Data members and member functions must have an access level. This access
level will be public, private or protected.
• Public members of a class can be accessed from anywhere within the
program.
• Private members of a class can only be accessed by member functions of the
class.
• Use of the public, private and protected access levels is the way in which C++
implements encapsulation, or information hiding.
• The collection of public data members and member functions defines the
logical properties of the class (i.e. what it does), and is sometimes called the
public interface of the class.
• A const member function cannot change the values of any of the data
members of the class.
18

• A constructor is a special member function that is called once when an object


of the class is instantiated.
• A destructor is a special member function that is called once when an object is
destroyed.
• If a data member is declared as static, there will only be one instance of it for
the entire class (regardless of how many objects are instantiated).
• Static member functions can be called even when there are no objects of the
class declared.
• Inspector member functions return the value of an attribute (data member) of
a class.
• Mutator member functions change or set the value of an attribute of a class.
• Facilitator member functions cause an object to perform some action or
service.

Note: The full source code listings for the examples in this handout can be found on the
FBE network server: to access them, open My Network Places, double-click on
MU-FBE, then FBE-SERVER and then browse to:
Courses\ICT122 – Object-Oriented Programming\src\Handout 1

Notes prepared by: FBE Computer Science Department.


19

You might also like