1 / 48

Implementing An OOD

(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

takoda
Download Presentation

Implementing An OOD

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. (Chapters 3, 4) Implementing An OOD

  2. 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.

  3. Elements of Good C++ Code • Readability • Consistent naming conventions • Code format • Comments • Language conventions • Coding style

  4. 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.

  5. Sample Script 8% flush Enter no. of cards in each hand (5-9): 7 Enter no. of hands to deal: 1000 DECK: 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 flushes 9%

  6. Chosen Object Classes • Simulation • Deck • Card • Pip • Suit

  7. 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

  8. Simulation Class Diagram

  9. 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 . . .

  10. 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. };

  11. 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)

  12. 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

  13. Pointers and Objects Unlike "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 nonpointer objptr->method if objptr is a pointer To avoid confusion and allow for dynamic object creation, a consistent style of class definition is used.

  14. Pointers and Objects (cont'd) Use the pointer type Simulation when declaring: - variables - parameters - data fields Use the class type SimulationInfo to create an object with new. Once pointers exist, use the "->" form of reference for both method and data access. Finally, explicitly free all objects with delete.

  15. 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::blankUp • When 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)

  16. 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.

  17. flush Main Program main() { Simulation s = new SimulationInfo; s->getdata(); s->simulate(); s->report(); s->free(); }

  18. 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

  19. Naming Conventions in C++ Identifier TypeExamples Type name Integer Simulation State Method name solve simulate checkFlush Field name (data) flush_count problem problem_ Local variable i count Constant NUM_TILES

  20. Standard Types The basic type names of C++ do not conform to the naming 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;

  21. 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)

  22. Header Files All 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

  23. 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

  24. Multiply Defined Symbols Foo.H #include "Bar.H" #include "Baz.H" . . . Bar.H Baz.H <symbols in here are multiply defined> #include "Bar.H" . . .

  25. 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

  26. 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.

  27. 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() { . . . }

  28. Memory Management Consider the SimulationInfo Constructor: 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 are allocated at run time.

  29. 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.

  30. 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

  31. Dangling Pointer References ptr = new ClassInfo(. . .); . . . delete ptr; . . . <code that later uses ptr again> ClassInfo Object ptr ptr Who knows what ptr is pointing to now. ptr ptr "Weird and wondrous" behavior ensues Partial Solution: follow the delete with ptr = NULL;

  32. Memory Leaks Suppose the following is in a loop: ptr = new ClassInfo(. . .); . . . <loop ends without any delete> ClassInfo Object1 ClassInfo Object2 ClassInfo Object3 ptr ClassInfo Object4 ClassInfo Object5 . . .

  33. 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).

  34. Memory Management in the flush Program SimulationInfo Object creates creates creates Deck Pointer, DeckInfo Object Array of 9 Card Pointers Array of 4 Integers

  35. DeckInfo Class class DeckInfo { private: CardArray cd_array; // 52-element array to hold cards public: 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. };

  36. DeckInfo Constructor DeckInfo::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 creates Array of 52 Card Pointers, 52 CardInfo Objects

  37. CardInfo Class class CardInfo { private: Integer deck_position; // This card's deck_position Suit the_suit; // This card's suit Pip the_pip; // This card's pip public: 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. };

  38. CardInfo Constructor CardInfo::CardInfo(Integer n) { deck_position = n; the_suit = new SuitInfo(n); the_pip = new PipInfo(n); } CardInfo Object creates Suit Pointer, SuitInfo Object Pip Pointer, PipInfo Object

  39. Summary of Memory Construction 1 SimulationInfo 1 Deck 1 DeckInfo 9 Cards 4 Integers 52 Cards, 52 CardInfos 52 Suits, 52 SuitInfos, 52 Pips, 52 PipInfos

  40. 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

  41. 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 memory created by a simulation is returned (freed).

  42. 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

  43. DeckInfo::free() Method 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; } • 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!

  44. CardInfo::free() Method void CardInfo::free() { delete the_suit; delete the_pip; delete this; } • A SuitInfo and a PipInfo object are deleted • Since the SuitInfo and PipInfo constructors do not create any new objects, we are done.

  45. Simulating a Dynamic Multidimensional Array in C++ C++ only allows dynamic one-dimensional arrays. However, some structures are best thought of in terms of rows and columns. For example, a 4x4 matrix of cards. So we must use the row and column to convert into a single dimension index.

  46. Dynamic Multidimensional Arrays (cont'd) An abstract 2-D array like: col 0 1 row 2 3 0 1 2 3 is represented in memory as: 0 15 10 row * 4 + col = 2 * 4 + 2 = 10

  47. 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 handled similarly.

  48. 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;

More Related