implementing an ood

48
Implementing An OOD (Chapters 3, 4)

Upload: takoda

Post on 25-Feb-2016

53 views

Category:

Documents


1 download

DESCRIPTION

(Chapters 3, 4). Implementing An OOD. Two Basic Steps. Convert the class diagram into C++ class declarations (header file) Convert the pseudocode into C++ methods (code file). Separation of files facilitates separate compilation , covered later. Elements of Good C++ Code. Readability - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Implementing An OOD

Implementing An OOD

(Chapters 3, 4)

Page 2: Implementing An OOD

Two Basic Steps

Convert the class diagram into C++ class declarations (header file)

Convert the pseudocode into C++ methods (code file)

Separation of files facilitates separate compilation, covered later.

Page 3: Implementing An OOD

Elements of Good C++ Code

1) Readability2) Consistent naming conventions3) Code format4) Comments5) Language conventions6) Coding style

Page 4: Implementing An OOD

Example: flush Program Problem Statement:

write a program that represents a deck of cards, simulates the dealing of poker hands, and estimates the probability of dealing a flush, that is, a

hand with at least five cards of the same suit.

Page 5: Implementing An OOD

Sample Script8% flush

Enter no. of cards in each hand (5-9): 7

Enter no. of hands to deal: 1000DECK:8D 1C 8H 5S 7C 2D 1H 10D 2S 6D 7S 2H 11H 10S 13C 11D 3C 3D 3H 9H 10C 2C 10H 7D 6H 12S 6C 3S 9D 1D 11S 5H 13D 7H 9S 4C 6S 8S 12D 5D 1S 9C 13H 5C 13S 4D 12C 8C 4S 11C 4H 12H

In 1000 7-card hands there were 35 flushes9%

Page 6: Implementing An OOD

Chosen Object Classes

Simulation Deck Card Pip Suit

Page 7: Implementing An OOD

Simulation Class Aspects

contains a Deck object manages the simulation of the dealing of multiple

hands determines a frequency distribution of flushes methods should be provided for:

creating a Simulation object getting simulation parameters from user managing the simulation, including memory reporting results

Page 8: Implementing An OOD

Simulation Class Diagram

Page 9: Implementing An OOD

Simulation Class Implementation in C++

class SimulationInfo {private: Deck the_deck; // The current deck CardArray one_hand; // The current hand IntArray suit_counts; // Suit counts in current

// hand Integer flush_count; // Total flush count Integer num_hands; // Total number of hands // to deal Integer hand_size; // Hand size (5-9 cards) Integer hands_per_deck;// Number of hands that // can be dealt per deck . . .

Page 10: Implementing An OOD

Simulation Class (cont'd) . . .public: SimulationInfo(); // Creates a new deck,

// space for one hand, // and suit count array. void free(); // Returns memory created by

// constructor. void getdata(); // Prompts for hand size and

// number of hands. void simulate(); // Performs the dealing simulation. void report(); // Reports results.private: void loopThroughHands(); // Implements outer loop of

// simulation. void dealAndCheckHand(); // Deals and checks one hand for

// a flush. void initSuitCounts(); // Initializes suit counts to zero. void incSuitCount(); // Increments suit count for each

// card in hand. void checkFlush(); // Checks suit counts for values

// >= 5 and increments flush // count if appropriate.

};

Page 11: Implementing An OOD

Elements of a Good C++ Class Definition

Comments describe fields and methods when appropriate

Blank lines promote readability Public methods precede private methods Method argument names are provided Data names are private (or protected) Methods not called externally are private Class constructor and destructor are explicitly

defined (even though C++ can do it implicitly)

Page 12: Implementing An OOD

Relationship Between Types Simulation and SimulationInfo

SimulationInfo is a C++ class type Simulation is a C++ pointer type Nearly every reference to a simulation will be via

the pointer type One main exception: class construction Why? Because C++ forces us to distinguish

between pointer and pointee We must deal with pointers, and we must give

back the memory to which they point

Page 13: Implementing An OOD

Pointers and ObjectsUnlike "pure" OOP languages like Java, Smalltalk, and Eiffel, C++ distinguishes between objects and pointers to them.

Thus there are two different syntaxes for method invocation:

obj.method if obj is a nonpointerobjptr->method if objptr is a pointer

To avoid confusion and allow for dynamic object creation, a consistent style of class definition is used.

Page 14: Implementing An OOD

Pointers and Objects (cont'd)Use the pointer type Simulation when declaring:

- variables- parameters- data fields

Use the class type SimulationInfo to create anobject with new.

Once pointers exist, use the "->" form of referencefor both method and data access.

Finally, explicitly free all objects with delete.

Page 15: Implementing An OOD

Pointers and Objects (cont'd) In general the actual class name, like SimulationInfo, is only used with the new operator. Exceptions:When referencing or calling a static method

Example: StateInfo::blankUpWhen small pieces of structured data (like a graphics

point) are copied over and over. These should be coded as structs instead of classes.

When a class is meant to act as a primitive element of the language (like a complex or rational number)

Page 16: Implementing An OOD

Using typedef for Clarity

We want to limit use of the C/C++ pointer token (*) for both clarity and similarity to Java

We use typedef for this purpose:

typedef <existing type> <new type identifier>;

typedef class SimulationInfo * Simulation;typedef class DeckInfo * Deck;typedef class CardInfo * Card;typedef class PipInfo * Pip;typedef class SuitInfo * Suit;

If the typedef appears before the class definition,the class modifier is required as a forward reference.

Page 17: Implementing An OOD

flush Main Program

main() { Simulation s = new SimulationInfo; s->getdata(); s->simulate(); s->report(); s->free();}

Page 18: Implementing An OOD

Virtues of this Approach Pointer references are much more efficient than

class references as: class instance variables (construction time) method parameters (call by value)

Enforces the discipline of dynamically creating all objects from the heap, and returning objects to the system when no longer needed.

Facilitates syntax so that all object data or method references are made using obj->data or obj->method

Page 19: Implementing An OOD

Naming Conventions in C++Identifier Type ExamplesType name Integer

SimulationState

Method name solvesimulatecheckFlush

Field name (data) flush_countproblemproblem_

Local variable icount

Constant NUM_TILES

Page 20: Implementing An OOD

Standard Types

The basic type names of C++ do not conform to thenaming conventions. So use typedef to solve this:

typedef int Integer;typedef int * IntArray;typedef char Boolean;typedef char Character;typedef double Float;typedef char * String;typedef String * StringArray;typedef Card * CardArray;

Page 21: Implementing An OOD

File Structure

Class and method definitions should be system- atically broken up into separate files, so that:

Readability is enhanced Changes are localized Program pieces can be separately compiled

C++ systems are composed of two types of files: Header files: contain declarations only (.H type) Code files (.cc or .C type)

Page 22: Implementing An OOD

Header FilesAll header files have a common structure. Example:

// ****************************************// file: SolverInfo.H// author: T. Colburn// purpose: General problem solver header file// modified: 09/11/02// ****************************************

#ifndef SOLVERINFO_USED#define SOLVERINFO_USED

#include "ProblemInfo.H"

class SolverInfo { . . .};

#endif

Page 23: Implementing An OOD

Header File Structure

A block comment shows file name, description, author, and any version or modification information

The #ifndef-#define-#endif is a "guard" against the file being included more than once (see next slide)

Toward the top should be parameters (consts), typedefs, and enumerations (in the example, these are included from ProblemInfo.H)

After that, the declarations of the actual classes

Page 24: Implementing An OOD

Multiply Defined Symbols

#include "Bar.H"#include "Baz.H". . .

#include "Bar.H". . .

<symbols in here aremultiply defined>

Foo.H

Bar.H Baz.H

Page 25: Implementing An OOD

Levels of Header Files Unless the program is fairly trivial, there should be

a header file for each class: SolverInfo.H ProblemInfo.H StateInfo.H ActionInfo.H ActionListInfo.H

In your lab exercise, you can have one header file for all classes:

Flush.H

Page 26: Implementing An OOD

Code Files Code files implement the methods declared in

header files. There should be one code file for each class, e.g. SolverInfo.cc, ProblemInfo.cc. etc.

Each code file should have a block comment at the top, and #include its corresponding header file.

Code files should have no local definitions, like enumerations or non-class support functions (should be private static methods instead).

Method bodies should be limited in size to what can be displayed on one screen.

Page 27: Implementing An OOD

Code File Example// *****************************************// file: SolverInfo.cc// author: T. Colburn// purpose: Implements SolverInfo class methods// modified: 09/11/02// *****************************************

#include <iostream.h>#include "SolverInfo.H"

SolverInfo::SolverInfo(Problem p) { . . .}

void SolverInfo::solve() { . . .}

String SolverInfo::promptActionName() { . . .}

Page 28: Implementing An OOD

Memory Management

SimulationInfo::SimulationInfo() { the_deck = new DeckInfo(); one_hand = new Card[9]; suit_counts = new Integer[4];}

Note that memory is allocated dynamically, that is,the DeckInfo object and supporting arrays areallocated at run time.

Consider the SimulationInfo Constructor:

Page 29: Implementing An OOD

Memory Management Problems Array out of bounds Dangling pointer references Memory leaks

Memory management is the biggest problem when using C++.

Solution: Plan memory management as part of the design.

Page 30: Implementing An OOD

Array Out Of Bounds

Since arrays are represented simply as pointers to memory, C++ does not check array bounds

Any array operation must have explicit bounds checks put in by programmer

Whenever an array is passed, its size should also be passed

Page 31: Implementing An OOD

Dangling Pointer Referencesptr = new ClassInfo(. . .);

.

.

.

delete ptr;...

<code that later uses ptr again>

ClassInfoObjectptrptr

ptrptr Who knows whatptr is pointing tonow.

"Weird and wondrous" behavior ensues

Partial Solution: follow the delete with ptr = NULL;

Page 32: Implementing An OOD

Memory LeaksSuppose the following is in a loop:

ptr = new ClassInfo(. . .);...

<loop ends without any delete>

ClassInfoObject1

ClassInfoObject2

ClassInfoObject3

ClassInfoObject4

ClassInfoObject5

ptr

.

.

.

Page 33: Implementing An OOD

Preventing Memory Leaks

Use automatic garbage collection (not currently available in C++)

Do reference counting. Each object keeps a count of its users. When the count reaches zero, the object is deleted.

Assign an owner to each object whenever possible, and have the owner be responsible for freeing memory (our approach).

Page 34: Implementing An OOD

Memory Management in the flush Program

SimulationInfoObject

Array of 9 Card Pointers

Deck Pointer,DeckInfo Object Array of 4 Integers

creates creates creates

Page 35: Implementing An OOD

DeckInfo Class

class DeckInfo {private: CardArray cd_array; // 52-element array to hold cardspublic: DeckInfo(); // Create the deck by allocating // cd_array and creating a new

// card for each element. void free(); // Return memory created by

// constructor. void shuffle(); // Shuffle deck by randomly

// swapping elements. void deal(Integer, Integer, // Deal cards into a hand.

CardArray); void print(); // Print all cards in the deck.};

Page 36: Implementing An OOD

DeckInfo ConstructorDeckInfo::DeckInfo() { cd_array = new Card[52]; // Create new card array for (Integer i = 0; i < 52 ; i++) // Fill array cd_array[i] = new CardInfo(i); // with new cards}

DeckInfo Object

Array of 52 CardPointers,52 CardInfoObjects

creates

Page 37: Implementing An OOD

CardInfo Classclass CardInfo {private: Integer deck_position; // This card's deck_position Suit the_suit; // This card's suit Pip the_pip; // This card's pippublic: CardInfo(Integer n); // Create a new card with suit and // pip depending on deck_position.

void free(); // Return space for this card and // its suit and pip objects.

Pip getPip(); // Retrieve pip object for this // card.

SuitInfo::type getSuitType(); // Retrieve suit type for this // card.

void print(); // Print this card by printing pip // value and suit.};

Page 38: Implementing An OOD

CardInfo Constructor

CardInfo::CardInfo(Integer n) { deck_position = n; the_suit = new SuitInfo(n); the_pip = new PipInfo(n);}

CardInfo Object

Pip Pointer,PipInfo Object

Suit Pointer,SuitInfo Object

creates

Page 39: Implementing An OOD

Summary of Memory Construction1 SimulationInfo

9 Cards1 Deck1 DeckInfo

4 Integers

52 Cards,52 CardInfos

52 Suits,52 SuitInfos,52 Pips,52 PipInfos

Page 40: Implementing An OOD

Summary of Memory Construction (cont'd)

One simulation creates a total of 328 pointers and objects

If simulations were created over and over in a loop (very common with simulations in general), memory would be used up fast

This is a classic memory leak Solution: make sure that when a simulation is

over, all memory created by it is returned

Page 41: Implementing An OOD

Recall flush Main Program

main() { Simulation s = new SimulationInfo; s->getdata(); s->simulate(); s->report(); s->free();}

The free method must make sure that all memorycreated by a simulation is returned (freed).

Page 42: Implementing An OOD

SimulationInfo::free() Method

void SimulationInfo::free() { the_deck->free(); // Return memory for all cards delete [] one_hand; // Return memory for hand array delete [] suit_counts; // Return memory for suit counts // array delete this; }

one_hand and suit_counts, being arrays of primitive objects (pointer and Integer), can be returned using the C++ delete[] operator

The rest must be handled by the DeckInfo::free() method

Page 43: Implementing An OOD

DeckInfo::free() Method

cd_array, being an array of pointers, can be deleted

However, each CardInfo object must be handled individually.

Note: cd_array must not be deleted first!

void DeckInfo::free() { for (Integer i = 0; i < 52; i++) // Return memory cd_array[i]->free(); // for each card delete [] cd_array; // Return memory

// for card array delete this;}

Page 44: Implementing An OOD

CardInfo::free() Method

A SuitInfo and a PipInfo object are deleted Since the SuitInfo and PipInfo constructors

do not create any new objects, we are done.

void CardInfo::free() { delete the_suit; delete the_pip; delete this;}

Page 45: Implementing An OOD

Simulating a Dynamic Multidimensional Array in C++

C++ only allows dynamic one-dimensional arrays.However, some structures are best thought of interms of rows and columns.

For example, a 4x4 matrix of cards.

So we must use the row and column to convert into asingle dimension index.

Page 46: Implementing An OOD

Dynamic Multidimensional Arrays (cont'd)

An abstract 2-D array like:

is represented in memory as:

row

col

row * 4 + col = 2 * 4 + 2 = 10

0 10

0123

0 1 2 3

15

Page 47: Implementing An OOD

Dynamic Multidimensional Array Example

CardArray cd_matrix;Integer row, column;Integer index;

row = 2;column = 2;cd_matrix = new CardInfo[4*4];index = row*4+column;cd_matrix[index] = new CardInfo(...);

Arrays of 3 dimensions and more must be handledsimilarly.

Page 48: Implementing An OOD

Use of Constants

Using the preprocessor, as in:

#define PI 3.14159

should be avoided in C++. Why? Strictly speaking, the preprocessor is an extension to the language and not part of the language itself.

Instead, use the const declaration:

const Integer PI = 3.14159; const Integer NUM_TILES = 8;