1Department of Computer Science and Engineering, HKUST
HKUST SummerProgramming Course 2008
Class~ The essence of Object Oriented Programming
2
Overview
Difference between struct and class Abstract data type Class components Object Oriented Programming
Why object oriented? OOP Features
Data Abstraction Encapsulation / Information Hiding
Class Declaration and Class Definition
3
Overview Class Name: Name Equivalence Class Data Members
Forward Declaration Initialization
Class Member Functions Constant Member Functions Inline Functions
Member Access Control How are Objects Implemented? “this” Pointer Class Scope and Scope Operator ::
Static Constant Data Member Class Object Initialization
4
Difference between struct and class
The only difference between class and struct: In struct, variables and function are “public” if you don’t
specify. In class, they are “private” by default.
5
Abstract data type
int, char, double and others are pre-defined data types. On the other hand, class is a user-defined type or an abstract data type.
Variable of a class, is called an “object”. For example, we have a class called Fruit, then we can define an object “apple” of this type.
Fruit apple;
Object apple is said to be an “instance” of the Fruit class.
Object (Variable)Class (Abstract Data Type)
6
class Stack{
private:
int size; // max size of storage
int top; // index of the next available space
int* data; // data storage
public:
Stack(int N); // a constructor
~Stack(); // a destructor
// basic operations
void push(int x); // add another datum
int pop(); // get the most recent datum
// status operations
int num_elements() const;
bool empty() const;
bool full() const;
};
Access Modifiers
Member Functions
Data Members
Remember this semicolon.
Class Definition (stack.h)
7
Class components Access modifiers
To control the access right of members inside the class.
Data member Class member for holding data.
Member function (aka Function Member, Method) Class member that perform actions on data members.
Constructor First function to be called when an object is going to be
created. Its name is the same as that of the class.
Destructor Last function to be called when an object is destroying. Its
name is the name of the class preceded by a ‘~’.
8Department of Computer Science and Engineering, HKUST
Object Oriented Programming
Concepts
9
Why object oriented?
For example,const int MAX_ALTITUDE = 11000;
const int MAX_SPEED = 960;
struct Airplane{
int altitude;
int speed;
};
void takeoff(Airplane plane);
void descend(Airplane plane, int feet);
10
Why object oriented?
There are some constraints on the Airplane class Altitude of airplane must be >= 0 but less than some
constants (MAX_ALTITUDE). Not all speeds are possible at all altitudes.
altitude
Max p
oss
ible
sp
eed
0
11
Why object oriented?
Can’t guarantee every access considers these constraints Altitude and speed are accessible throughout the
entire program.
If not all members in a programming team follows the constraints strictly, then logical error will be resulted.
Difficult to debug if the values are found to be wrong.
You need to search over the entire program to fix the bugs.
12
Why object oriented?
How can constraints be enforced? We can define a restricted set of functions that access the
value of altitude and speed (of Airplane) to ensure data consistency.
Other parts of the program can access the value of altitude and speed only indirectly through this restricted set of functions.
We only have to ensure the constraints be considered in this restricted set of functions (instead of the entire program).
Easier to maintain the code, testing and debugging.
13
Why object oriented?
How can we ensure that the Airplane structure’s members are only accessed by a restricted set of functions? In standard procedural programming languages (e.g. C),
WE CAN’T ...
This inspired the development of Object-Oriented Programming (OOP) languages, E.g., C++ and Java
14
OOP Features
Data abstraction Encapsulation / Information Hiding Inheritance (Reusability of code) Polymorphism
We will discuss the first two features first.
15
Data Abstraction
A data abstraction is a simplified view of an object. includes only features one is interested in while hides away
the unnecessary details. E.g. An airplane class is not as complicated as a real plane, it
can only let you control the speed and direction of a plane.
In programming languages, a data abstraction becomes an abstract data type or a user-defined type. E.g.
Fruit apple;
In OOP, it is implemented as a class.
16
Encapsulation / Information Hiding An abstract specification tells us the behavior of an
object independent of its implementation. It tells us what an object does independent of how it works.
Information hiding is also known as data encapsulation, or representation independence.
The principle of information hiding: Design a program so that the implementation of an object
can be changed without affecting the rest of the program. For example, you can create a stack using linked-list or
array. That will not affect the stack’s public interface. A stack should support “push” and “pop”
17
Classes and Programming Conceptually a class is a blueprint or a design of something.
When we create a product according to this blueprint, that is an object. E.g. to build five cars according to a Car blueprint
Although “object oriented” is a way to simulate our concepts in real-world, we can’t forget its “programming” part.
That means a class should have its own functions, data structures, data types, etc.
We have to learn a lot of syntax and special behavior of C++ in order to carry out those object oriented concepts.
18
Class Declaration and Class Definition As in function, we can introduce the name of a
class, without defining it Class Definition
Define what a class contains What is its data member and member functions Including the type of data members and the
declaration of member functions Class Declaration
Introduce a class name only Usage will be covered later
Class Implementation Include all definition of the member functions
19
class Stack; // class declaration
class Stack{ // class definition
private:
int size; // max size of storage
int top; // index of the next available space
int* data; // data storage
public:
Stack(int N); // declaration of constructor
~Stack(); // declaration of a destructor
void push(int x); // declaration of a member function
int pop();
int num_elements() const;
bool empty() const;
bool full() const;
};
Header file (stack.h)
20
#include “stack.h” // remember to include the header file
// class implementation (defines all member functions)
Stack::Stack(int N) {
size = N;
top = 0;
data = new int[size];
}
Stack::~Stack(){
delete [] data;
data = NULL;
}
void Stack::push(int x){
if ( full() )
cout << “ERROR: Stack is already full” << endl;
else data[top++] = x;
}
Source file (stack.cpp)
21
int Stack::pop(){
if ( empty() ){
cout << “ERROR: Stack is empty” << endl;
return -9999;
}
return data[--top];
}
int Stack::num_elements() const{
return top;
}
bool Stack::empty() const{
return ( top == 0 );
}
bool Stack::full() const{
return ( top == size );
}
Source file (stack.cpp) […continue]
22
Class Name: Uniqueness
The name of classes cannot be used in two definitions.
class W { int a; }; // error, double
class W { double b; }; // definition
// OK, a class can be declared multiple times
class R; // class declaration
class R { int a; }; // class definition
class R; // OK: another declaration
23
Class Name: Name Equivalence
A class definition introduces a new abstract data type. C++ relies on name equivalence (and NOT structure equivalence) for class types.
class X { int a; }; // define two different classes
class Y { int a; }; // with same structure
X x; // create two objects for class X and Y
Y y;
x = y; // error: type mismatch; x and y are objects
// of different types
24
Class Data Members
Data members can be of a pointer or reference of its own type:
class A {
A* pointerA;
A& refA;
A objA; // ERROR: cannot use its own type, except
// pointer/reference
};
Using objA inside the definition of class A makes the size of object infinite, therefore it is not allowed.
However, pointer and reference must occupy 4 bytes only. It is allowed in the definition of class A.
25
Class Data Members - Forward Declaration
Data members of a class can be of any basic type, or any user-defined type if they are declared/defined: A forward declaration for class pointers:
class Cell; // forward declaration of Cell class
class Stack {
int size;
Cell *top; // OK: because we declared that there is
// a Cell class (forward declaration)
Cell x; // Error: the definition of Cell class
// is not complete!
};
class Cell { int a; };
class Stack{ Cell x; }; // OK, Cell is already defined
26
Recursively uses user-defined type in class definitionclass A; // forward declaration
class B{ // definition of class BA* pointerA;
};
class A{ // definition of class AB* pointerB;B objB; // this is also allowed
};
Class Data Members - Necessity of Forward Declaration
27
Class Data Members - Initialization
Data members can NOT be initialized (give initial values) inside the class definition.class Stack {
// ...
int top = 0; // Error: class data member
// cannot be initialized here
};
Initialization should be done with appropriate constructors, or member functions.Stack::Stack(int N) { // constructor definition
top = 0; // It is ok
}
28
Class Member Functions These are the functions declared inside the body of a class, but
they can be defined in two ways: Within the class body, they are inline functions
class Stack {// ...void push(int x) { /* ... */ }int pop() { /* ... */ }
}; Outside the class body
class Stack {// ... void push(int x);int pop();
};void Stack::push(int x) { /* ... */ }int Stack::pop() { /* ... */ }
29
Constant Member Functions
‘const’ keyword can guarantee that the member function won’t modify the invoking object.
class Stack {
…
int num_elements() const { return size; } // OK
int pop() const { --top; return top; } // ERROR
};
To define a function outside the classint Stack::num_elements() const { return size; }
30
Constant Member Functions
Also, for a constant object, it can call its constant member functions only. Calling constructor and destructor are exceptions,
because they can’t be declared as constant functions.Stack stk_a;
const Stack stk_b;
stk_a.num_elements(); // OK
stk_b.num_elements(); // OK
stk_a.pop(); // OK
stk_b.pop(); // ERROR: constant object// accesses non-const
member
31
Inline Functions
Member function can also be inlinedclass Stack{
// ...
int num_elements() const { return top; }
};
int main() {
Stack stackA;
cout << stackA.num_elements() << endl;
return 0;
}
The above cout statement is similar tocout << stackA.top << endl;
32
Inline Functions
On the other hand, when you define a member function inside the class, it is automatically treated as an inline function.class Stack {
// ...
// define the member function inline
int num_elements() const { /* ... */ }
int pop() { /* ... */ }
};
33
Inline Functions To enhance readability, you may also define inline
functions in the same header file with the class but outside the class definition.// Stack.hclass Stack {
…inline void push(int x); // an inline function
};
// put the inline function out of the classinline void Stack::push(int x) {
top = x; ++top;}
34
Inline Functions
Recall that C++ compilers may NOT honor your inline declaration.
The inline declaration is just a hint to the compiler.
Compiler still has the freedom to choose whether to inline your function or not, especially when the function is large.
35
How are objects implemented?
Each class object gets its own copy of the data members.
All objects of the same class share one copy of the member functions.int main()
{
Stack x(2), y(3);
x.push(1);
y.push(2);
y.pop();
}
36
Member Access Control A member (data or function) of a class can be:
public : accessible to anybody (inside or outside the class).
private : accessible only to member functions (include another object of the same class). It is mainly used to enforce information hiding.
class A {private: int x;public:
A() { x = 3; } // initialize x to 3void add(A another) { x = another.x + x; } // it is ok to access another object of the
// same class. Not prohibited by private.
}; protected: it will be discussed later.
37
Accessing Member Functions / Data Members Use member access operator (.)
Stack stackA(12);stackA.push(3); // call a member function
// in Stack class
Use dereference member access operator (->)// a pointer to a Stack objectStack* stackA = new Stack(12);stackA->push(3); It is equal to a deference operator plus a member access
operator, i.e.(*stackA).push(3);
You can also use these operators to access the data members
38
“ this” Pointer Each class member function implicitly contains a pointer of its
class type named “this”. When an object calls the function, this pointer is set to point to
the invoking object. For example, the C++ compiler developed by AT&T Bell Labs
will automatically translate the function void Stack::push(int x)
in the class Stack to a unique global function by adding a new argument:
void Stack::push(Stack* this, int x) {if ( this->full() )
cout << “ERROR: Stack is already full” << endl; else
this->data[ (this->top)++ ] = x;}
a.push(x) becomes push(&a, x).
39
“ this” Pointer of constant member function
Since a constant member function cannot modify the data members, the “this” pointer is declaraed as a constant pointer type
void Stack::num_elements(const Stack* this) {
return top;
// return this->top; // equivalent
}
40
Necessity of using “this” Pointer Return an object by “this”.
class Complex {private:
float real;float imag;
public:// Addition of complex numbersComplex add( const Complex& x) {
real += x.real;imag += x.imag;return *this; // return the object itself
}};
Use the above code, we can do something like thisComplex x, y, z;// ...Complex a = z.add( x.add(y) );
41
Class Scope and Scope Operator ::
C++ statically binds name occurrences to declarations at compile time
int height; // global “height”
class Hill {
int height; // local “height”
Hill() { height = 0; } // constructor
}; Which “height” does Hill() using?
Hill::height (the one defined in the class Hill) How to access the global “height” inside class Hill?
::height
42
Class Scope and Scope Operator ::#include <iostream>using namespace std;
int height;
class Hill {private:
int height;public: Hill() { // constructor
::height = 0; // Access global “height” using ::height = 7; // Access local “height”
} void print() {cout << "local height " << height << endl; }};void main() { Hill h; h.print(); cout << "global height " << height << endl;}
43
Constant Data Member
Sometimes, a data member should not be changed after the object has been constructed.class Airplane {
private:
const string MODEL_NUMBER;
int altitude;
int speed;
public:
Airplane(string modelNumber, int altitude, int speed);
void takeoff(Airplane plane);void descend(Airplane plane, int feet);
void print() const;
};