1 data abstraction: the walls (walls & mirrors - chapter 3)

65
1 Data Abstraction: The Walls (Walls & Mirrors - Chapter 3)

Post on 20-Dec-2015

238 views

Category:

Documents


0 download

TRANSCRIPT

1

Data Abstraction: The Walls

(Walls & Mirrors - Chapter 3)

2

When one family builds a wall, two families benefit from it. Chinese proverb

Before I built a wall I’d ask to know What I was walling in or walling out.

Robert Frost (“Mending Wall”)

Before abstraction everything is one, but like chaos; after abstraction everything is united again, but this union is a free binding of autonomous, self-determined beings.

Friedrich von Hardenberg (1798)

3

Abstract

• Webster’s dictionary defines “abstract” as, “disassociated from any specific instance.”

– “University” is abstract; “NJIT” is a specific instance.

– “NJIT course” is abstract; “CIS 114” is a specific instance.

– “CIS114 student” is abstract; “Mary Jones” is a specific instance.

• If you are thinking of something, but there isn’t a single, unique representation of it, then your idea is abstract.

4

Functional Abstraction vs. Data Abstraction

• Functional abstraction means that a function can be used without taking into account how the function is implemented.

• Access to the function is provided through a specific interface defined to invoke the function.

• Data Abstraction means that data can be used without taking into account how the data are stored.

• Access to the data is provided through a specific set of operations defined to examine and manipulate the data.

5

Functional Abstraction - Examples

When you use functions in any of the C++ standard libraries, you are taking advantage of functional abstraction. You don’t care how the functions are implemented, but only what they do and how to invoke them.

<iostream.h>: cin, cout, endl, setprecision( ), setw( )

<string.h>: strcat( ), strcmp( ), strcpy( ), strlen( )

<math.h>: ceil( ), sin( ), exp( ), log( ), pow( ), sqrt( )

6

Data Abstraction - Examples

When you use any of the C++ standard data types, you are taking advantage of data abstraction. You don’t care how the data are stored, but only what operations are provided and what properties are supported.

int i, j, k; // i + 0 = i, i + j = j + i,

// i*(j + k) = i*j + i*k

float x, y; // floor( x ) <= x, ceil( x ) >= x,

// x - y = x + ( -y )

char s[5] = {‘a’, ‘b’}; // s[0] < s[1], strlen( s ) = 2

7

Abstraction vs. Information Hiding

While functional (or data) abstraction provides access to a function (or data) through a specific interface, information hiding means that implementation details are hidden within a section of code and inaccessible from outside that section.

8

Abstract Data Type

• An abstract data type is a collection of data and a set of operations on them that is disassociated from how the data are stored and how the operations are implemented.

• Technically, all data types are abstract:

– No unique way to store the data bits,

– No need to know how the bits are stored,

– No need to know how operations are performed; only need to know what properties are supported when the operations are performed.

9

Abstract Data Type (Cont’d.)

• Typically, however, the term, “abstract data type,” (ADT) is reserved to refer to new types of data, defined by the programmer, where the implementation details are hidden from the user, and access to the data is provided through an interface to a specific set of operations.

• C++ classes provide this capability by restricting access to certain data through the use of specific operations defined by the programmer.

10

ADT - “Real Life” Examples

• An ADT is like:

– A home appliance (television, radio, refrigerator, etc.), since it can be used without having to know the physics and engineering behind how it works.

– A vending machine, since you can purchase a product without having to know how it counts the money, stores the product, or (if applicable) keeps the product cold.

– A clerk, since one can ask a clerk to file and retrieve documents without having to know how the documents are organized, where they are stored, or be concerned if the filing cabinets are replaced by different ones.

11

Abstract Data Type - Advantages

• An ADT can be used without having to know the details about how it was implemented.

• Due to changing needs (e.g. efficiency concerns, larger data values or data sets than planned, new hardware, etc.), the implementation may have to be changed.

– Without restrictions imposed by an ADT, development will likely make use of implementation details. Result: extensive program changes are required!

– An ADT insulates its user from implementation details. Result: required changes are localized.

12

Abstract Data Type - Advantages

• ADTs make it possible for multiple people to work on a the same computer program without knowing the details of each others’ implementation.

• ADT’s are like a contracts between programmers. If one of them (say, Joe) specifies what operations an ADT should support, another programmer (say, Fred) could implement it, and Joe doesn’t have to be concerned about how it was done.

13

Stack• A stack is like a cafeteria tray dispenser: First In, Last Out.

• Typical operations include:

– Push an item onto the stack.

– Pop an item from the stack.

– What’s on top of the stack?

– What’s the size of the stack?

• As long as these operations are supported, you don’t need to be concerned with whether the stack is implemented as an array, a linked list, or something else.

IN OUT

14

Set

• A set is an unordered collection of unique elements.

• Typical operations include:

– Create set A, containing elements a, b, c

– Delete set A

– For sets A, B: A B, A B, A, A B, A = B

– For element e: Add e to A, Delete e from A, e A

15

Set (Cont’d.)

• Suppose set A is implemented as an array of integers:

int A[MaxAsize] = {2, 4, 6, 8}; int Asize = 4;

• Knowing this, one could add an element to A by writing:

if( Asize < MaxAsize ) A[Asize++] = 6;

• Since 6 now appears twice in A, A is no longer a set.

• Also, if one wanted to change how set A is implemented, (for example, to a vector of bits), one would have to search through the entire program to find and change every place where operations on A are performed.

16

Set (Cont’d.)

• Implementation of set A would be more robust to illegal operations and more maintainable if it were implemented as an ADT.

• Since ADTs enforce information hiding, the only way to add or delete an element from A is by calling specific functions that have been written to preserve the properties of a set.

• Also, changing the implementation of set A requires changing only the implementation of the functions that manipulate A, not every place where the functions are called.

17

ADT List

• A list is an ordered collection of items (or elements).

• A list data type is not defined by the C++ language.

(An implementation is available in the Standard Template Library.)

• Steps to define an ADT List:

1) Determine what data are required.

2) Determine what operations are required.

3) Finally, choose an implementation that will support the operations on the data.

18

Defining an ADT List• What data are required?

– “Items” of a particular data type.

(Let’s define the items to be of type ItemType.)

• What operations are required?

– Create an empty list

– Destroy a list

– Determine the number of items in a list

– Insert an item at a given position in a list

– Remove the item at a given position in a list

– Retrieve the item at a given position in a list

19

Create an Empty List

List( );

is the default constructor (i.e. the constructor with no arguments). It should create a new, empty, List.

• Always define a default constructor.

– A compiler-generated constructor may not initialize data members to suitable values.

– If you write a constructor with arguments, the compiler will not generate a default constructor for you.

C++ declaration:

List L; // creates a new List named L

20

Destroy a List

• For this example, we shall assume that the compiler-generated destructor is used to destroy a List and free up the associated memory.

• Nothing needs to be written to accomplish this.

21

Number of Items in a List

int getLength( ) const;

should return the number of items in a List. Const means that this function cannot change any of List’s data members.

• This function is useful for determining if a List is empty or full.

C++ function call:

int nitems; List L;

...

nitems = L.getLength( ); // stores length of L in nitems

22

Insert an Item into a List

void insert( int pos, ItemType newItem, bool &success );

should insert newItem into a List at position pos. Success is true if insertion is successful, otherwise false.

C++ function call:

int pos; ItemType item; bool outcome;

List L;

...

L.insert( pos, item, outcome ); // inserts item at position

// pos in L

23

Remove an Item from a List

void remove( int pos, bool &success );

should remove the item at position pos in a List. Success is true if removal is successful, otherwise false.

C++ function call:

int pos; bool outcome;

List L;

...

L.remove( pos, outcome ); // removes the item at

// position pos in L

24

Retrieve an Item from a Listvoid retrieve( int pos, ItemType &dataItem, bool

&success ) const;

should retrieve the item at position pos in a List. Const means that this function cannot change any of List’s data members. Success is true if retrieval is successful, otherwise false.

C++ function call:

int pos; bool outcome; List L;

...

L.retrieve( pos, item, outcome ); // retrieves the item at

// position pos in L

25

Choose an Implementation

• Now that the data and operations on the data have been defined, we can choose an appropriate implementation for the ADT List.

• In fact, the preceding specifications could be handed off to another person to implement the ADT List. You shouldn’t have to be concerned about how the implementation is done as long as it conforms to these interface specifications.

• A C++ implementation of the ADT List as an array follows.

26

ADT List as a C++ Array

i: index for items[ MAX_LIST ]

pos: positions in ADT List

MAX_LIST-1k-1

k

3210

21 3 4

1912 5 . . . ??31824 . . .

MAX_LIST

size k

27

ADT List as a C++ Array

const int MAX_LIST = 100; // maximum List size

typedef int ItemType; // items in List are int’s

class List

{

public:

// declarations of public member functions

private:

ItemType items[ MAX_LIST ]; // array for List items

int size; // size of List

};

28

Member Function Definitions: Create a List; Get Its Length

List::List( ) : size( 0 ) { } // default constructor

// creates a new List and

// initializes its size to 0

int List::getLength( ) const

{

return size; // returns size of List

}

29

Member Function Definitions: Insert an Item into a List

void List::insert( int pos, ItemType newItem, bool &success )

{

success = bool( pos >= 1 && pos <= size+1

&& size < MAX_LIST );

if( success ) // pos is in range

{

for( int i = size; i >= pos; i-- ) // make room for newItem

items[ i ] = items[ i-1 ];

items[ pos-1 ] = newItem; // add newItem at pos-1

size++;

}

}

30

Member Function Definitions: Remove an Item from a List

void List::remove( int pos, bool &success )

{

success = bool( pos >= 1 && pos <= size );

if( success ) // pos is in range

{

for( int i = pos; i < size; i++ ) // remove item at pos-1

items[ i-1 ] = items[ i ];

size--;

}

}

31

Member Function Definitions: Retrieve an Item from a List

void List::retrieve( int pos, ItemType &datum,bool &success ) const

{

success = bool( pos >= 1 && pos <= size );

if( success ) // pos is in range

datum = items[ pos-1 ]; // retrieve item at pos-1

}

32

ADT Sphere

• What data are required?

– Radius of the sphere and the constant, • What operations are required?

– Create a sphere

– Set the radius of a sphere

– Determine the radius of a sphere

– Determine the diameter of a sphere

– Determine the circumference of a sphere

– Determine the surface area of a sphere

– Determine the volume of a sphere

33

Create a Sphere

Sphere( );

is the default constructor. It should create a new Sphere with default radius = 1.

Sphere( double initialRadius );

is an alternative constructor. It should create a new Sphere with radius initialRadius.

C++ declarations:

Sphere S; // creates a new Sphere named S, with radius 1

Sphere T( 12.8 ); // creates a new Sphere named T,

// with radius 12.8

34

Set and Get the Radius of a Sphere

void setRadius( double newRadius );

should set (or reset) the radius of a Sphere to newRadius.

double getRadius( ) const;

should return the radius of a Sphere. getRadius cannot change any of Sphere’s data members.

C++ function calls:

Sphere S; double Sradius;

S.setRadius( 10.0 ); // sets radius of S to 10.0

Sradius = S.getRadius( ); // stores radius of S in Sradius

35

Choose an Implementation

• Assuming that the remaining operations on a Sphere have been defined, we can choose an appropriate implementation for the ADT Sphere.

• A C++ implementation of the ADT Sphere follows.

36

ADT Sphere

const double PI = 3.14159;

class Sphere

{

public:

// declarations of public member functions

private:

double radius; // radius of the Sphere

};

37

Member Function Definitions: Create a Sphere

Sphere::Sphere( ) : radius( 1.0 ) { } // default constructor

// creates a new Sphere and

// initializes its radius to 1.0

Sphere::Sphere( double initialRadius ) :

radius( initialRadius ) { } // creates a new Sphere and

// initializes its radius to

// initialRadius

38

Member Function Definitions: Set and Get the Radius of a Sphere

void Sphere::setRadius( double newRadius )

{

radius = newRadius; // sets radius of the Sphere to

// newRadius

}

double Sphere::getRadius( ) const

{

return radius; // returns radius of the Sphere

}

39

ADT Colored Sphere

• What data are required?

– Color, in addition to data for Sphere

• What operations are required?

– Set the color of a Sphere

– Get the color of a Sphere

– Remaining operations are the same as for Sphere

• Inheritance can be used to make Sphere’s member data and operations available to the new ADT Colored Sphere.

40

Member Function Declarations

ColoredSphere( Color initialColor );

should create a new ColoredSphere with color initialColor.

ColoredSphere( Color initialColor, double initialRadius );

should create a new ColoredSphere with color initialColor and radius initialRadius.

void setColor( Color newColor );

should set the color of a ColoredSphere to newColor.

Color getColor( ) const;

should return the color of a ColoredSphere.

41

Implementation of a ColoredSphere

#include “Sphere.h” // include declarations for Sphere

enum Color{ RED, BLUE, GREEN, YELLOW };

class ColoredSphere : public Sphere // public member data and

{ // functions of Sphere can

// be used for ColoredSphere

public:

// declarations of public member functions

private:

Color color; // color of the ColoredSphere

};

42

Member Function Definitions:Create a ColoredSphere

ColoredSphere::ColoredSphere( Color initialColor ) :

Sphere( ) // invokes the default Sphere constructor

{ // to create a ColoredSphere

color = initialColor; // set color of Sphere to initialColor

}

ColoredSphere::ColoredSphere( Color initialColor,

double initialRadius ) : Sphere( initialRadius )

{ // create ColoredSphere with initialRadius

color = initialColor; // set color of Sphere to initialColor

}

43

Member Function Definitions:Set Color; Get Color

void ColoredSphere::setColor( Color newColor )

{

color = newColor; // set color of ColoredSphere

} // to newColor

Color ColoredSphere::getColor( ) const

{

return color; // return color of ColoredSphere

}

44

Pointers

(Walls & Mirrors - Beginning of Chapter 4)

45

Here be Dragons!

Ancient map

46

What’s a Pointer?

• A pointer variable is a variable that can contain the location of another variable as its value.

• The location of a variable is usually implemented by indicating its address in (RAM) memory.

• The location (or address) of a variable is called a pointer.

• Sometimes, for brevity, a pointer variable is simply called a pointer. You will need to be careful to understand whether pointer refers to a variable or the address of a variable.

47

Pointers -“Real Life” Examples

• Suppose that your friend, Sam, borrows your copy of Walls & Mirrors. In its place, he leaves you the note

Borrowed your Walls & Mirrors book.

Thanks, Sam

• This note is like a pointer, since it it not your book, but it tells you where to go to find it.

(The paper on which the note is written is like a pointer variable.)

48

Pointers - Graphical Representation

• A variable is often represented as a box.

• The value of the variable is written inside the box.

• If the variable is a pointer variable, containing a pointer, the box will contain the “tail” of an arrow that points to another variable.

Pointer variable

Other variable

49

Pointers - Suggestion

• If you have a problem with pointers, draw the layout.

• It may be difficult to understand what is going on without a graphical representation of the pointer relationships.

50

Pointer Declarations

int *iptr; // iptr is a pointer to an int

char *cptr; // cptr is a pointer to a char

float *fptr; // fptr is a pointer to a float

List *Lptr; // Lptr is a pointer to a List object

Sphere *Sptr; // Sptr is a pointer to a Sphere object

51

Pointer Operations

• Assignment: =

– A pointer variable can be assigned only a pointer (i.e. the address of a variable) or NULL (which equals 0).

• Comparison: = =, !=

– Pointers can be compared for equality.

• Addition/Subtraction: +, – Pointers can be incremented or decremented with an integer.

• Dereferencing: *

– *ptr returns the value of the object pointed to by ptr.

• Address of: &

– &ptr returns the address of ptr (i.e. pointer to ptr).

52

Pointer Operations - Address of

• The Address of operator & returns the address of an object.

float PI = 3.14159; float *PIptr;

&PI returns the address of the variable PI, not 3.14159 (the value stored in PI).

PIptr = &PI stores the address of variable PI in variable, PIptr.

&PIptr returns the address of variable PIptr.

53

Pointer Operations - Dereferencing

• The Dereferencing operator * returns the value of the object to which its operand points.

float PI = 3.14159; float *PIptr; float X;

PIptr = &PI; // PIptr contains the address of PI

X = *PIptr; // Value stored in PI (3.14159) is

// assigned to X

*(*(&PIptr)) = *PIptr = *(&PI) = PI = 3.14159

54

Pointer Initialization

int *ptr; // pointer to int declared, value undefined

int x = 5; // int declared and initialized to 5

cout << x; // prints 5

cout << *ptr; // Error! Prints undefined value, since ptr not

// initialized

ptr = &x; // ptr now contains the address of x

cout << *ptr; // prints 5

55

Pointer Initialization - Suggestion

• When a pointer variable is declared it is (by default) uninitialized. Therefore, where it is pointing is undefined.

• It’s a good practice to initialize newly declared pointer variables to the NULL pointer (= 0).

– This will insure that the pointer variable is not pointing anywhere it shouldn’t.

– This will help you determine if a valid pointer has been assigned to it.

if( ptr = = NULL )

cout << “ptr has not been initialized” << endl;

56

new Operator

• The operator new creates a new object of a given type.

• new returns a pointer to the newly created object.

ptr = new int;

ptr

new int variable

57

new Operator (Cont’d.)

• An object created with new does not have a name and is not declared.

• An object created with new can only be used by following (dereferencing) a pointer to it.

• You need to be careful to not lose the pointer to an object created with new, since there is no other way to access it.

• Memory that was allocated with new and has become inaccessible is called a memory leak.

• For programs that run for long periods of time, memory leaks can be the reason for system failure.

58

new Operator - Example 1

int *ptr; // pointer to int declared, value undefined

*ptr = 5; // Error! ptr contains invalid address and

// space for int not allocated

ptr = new int; // space for int allocated and pointer to it

// assigned to ptr

*ptr = 5; // 5 is stored in the int pointed to by ptr

59

new Operator - Example 2

int *p, *q; // declare two pointer to int variables

p = new int; // allocate space for an int; make p point to it

*p = 25; // store 25 in the int pointed to by p

What is the effect of the following?

q = p;

60

new Operator - Example 2 (Cont’d.)

Draw a picture!

qp

new int

25

61

new Operator - Example 3

int *p, *q; // declare two pointer to int variables

p = new int; // allocate space for an int; make p point to it

q = new int; // allocate space for an int; make q point to it

*p = 35; // store 35 in the int pointed to by p

What is the effect of the following?

*q = *p;

62

new Operator - Example 3 (Cont’d.)

Draw a picture!

p

new int 35

q

new int 35

63

new Operator - Example 3 (Cont’d.)

What would have happened if we had executed

q = p;

instead of

*q = *p;

64

new Operator - Example 3 (Cont’d.)

The new int, previously pointed to by q is LOST and cannot be recovered. This is called a memory leak.

p

new int 35 new int?

q

65

Arrays and Pointers

int a[50];

int *aptr = a;

a is equivalent to &a[0]

aptr = a; is equivalent to aptr = &a[0];

aptr+5 is equivalent to &a[5]

*(aptr+5) is equivalent to a[5]