Presentation is loading. Please wait.

Presentation is loading. Please wait.

6-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 Presentation Copyright.

Similar presentations


Presentation on theme: "6-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 Presentation Copyright."— Presentation transcript:

1 6-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 Presentation Copyright 1999, Franklin, Beedle & Associates Students who buy and instructors who adopt Computing Fundamentals with C++, Object-Oriented Programming and Design by Rick Mercer are welcome to use this presentation as long as this copyright notice remains intact.

2 6-2 Chapter 6: Class Definitions and Member Functions  Chapter Goals  Read and understand class definitions (interface and state). –Exercises and Programming Projects to reinforce reading and understanding new class interfaces  Implement class member functions using existing class definitions.  Apply some object-oriented design heuristics. –Exercises and Programming Projects to reinforce member function implementation

3 6-3 6.1 The Interface  Abstraction:  Act of using and/or understanding something without full knowledge of the implementation  Allows programmer to concentrate on essentials  how does a grid object move? Not to worry.  how does string::substr work? Don't need to know.  Abstract level: the interface  Implementation level: the algorithms and local objects in the member functions

4 6-4 6.1.1 Design Decisions with class bankAccount  bankAccount could have had  more operations  more state  It was kept simple because it is an introductory example.  An account number wasn't present because  it's easier to remember "Smith" than "217051931"

5 6-5 What is "good" design?  Design decisions may be based on making  a software component more maintainable  software that is easy to use  software that can be reused in other applications  There are usually tradeoffs to consider  software may get to market more quickly than the competitors even if it has known errors --- this is a tradition  There is rarely a perfect design  Design is influenced by many things

6 6-6 Interface == class definition  In a real-world bankAccount, there could be many more operations:  applyInterest, printMonthlyStatement, averageDailyBalance  choosing what operations belong to a class requires many design decisions  The design is captured by the class interface:  the collection of available messages that is captured in the C++ class definition see next slide

7 6-7 6.2 Class Definitions class class-name { public: class-name() ; // Default constructor class-name() ; // Default constructor class-name(parameter-list) ; // Constructor with parameters class-name(parameter-list) ; // Constructor with parameters function-heading ; // Member functions that modify state function-heading ; // Member functions that modify state function-heading ; function-heading ; function-heading const ; // Members that do not modify state function-heading const ; // Members that do not modify state function-heading const ; function-heading const ;private: object-declaration // Data members -- the state object-declaration // Data members -- the state object-declaration object-declaration } ;

8 6-8 class bankAccount { public: bankAccount(); bankAccount(); // post: construct a default bankAccount object // post: construct a default bankAccount object bankAccount(string initName, double initBalance); bankAccount(string initName, double initBalance); // post: Initialize bankAccount object with 2 arguments // post: Initialize bankAccount object with 2 arguments void deposit(double depositAmount); void deposit(double depositAmount); // pre: depositAmount > 0.00 // pre: depositAmount > 0.00 // post: credit depositAmount to this object's balance // post: credit depositAmount to this object's balance void withdraw(double withdrawalAmount); void withdraw(double withdrawalAmount); // pre: 0 <= withdrawalAmount <= balance // pre: 0 <= withdrawalAmount <= balance // post:debit withdrawalAmount from object's balance // post:debit withdrawalAmount from object's balance double balance() const; double balance() const; // post: return this object's current account balance // post: return this object's current account balance string name() const; string name() const; // post: return this object's identification name // post: return this object's identification nameprivate: string my_name; // The unique account identification string my_name; // The unique account identification double my_balance; // Stores the current balance double my_balance; // Stores the current balance}; Class definitions: An example with comments

9 6-9 Class Definitions continued  The class definition  shows what messages are available  provides information necessary for sending messages it has a collection of member function headings  member function name, return type, number of parameters  represents the interface, which is the collection of available messages

10 6-10 Class Definitions continued  The following things can be determined from a class definition  The class name  The name of all member functions  The return type of any non-void function  The number and class of arguments required in any member function call  The action of each member function through postconditions if it has comments, that is

11 6-11 Objects are a lot about Operations and State  The function-headings after public: represent the messages that may be sent to any object  The data-members after private: are what stores the state of any object  every instance of a class has it own separate state

12 6-12 The same class without pre and post conditions code oriented class bankAccount { public: // OPERATIONS //--constructors bankAccount(); bankAccount(); bankAccount(string initName, double initBalance); bankAccount(string initName, double initBalance);//--modifiers void deposit(double depositAmount); void deposit(double depositAmount); void withdraw(double withdrawalAmount); void withdraw(double withdrawalAmount);//--accessors double balance() const; double balance() const; string name() const; string name() const; private: // STATE string my_name; string my_name; double my_balance; double my_balance;};

13 6-13 class diagram summary of operations and state

14 6-14 Sample Messages #include #include using namespace std; #include "baccount" // for class bankAccount int main() { // Test drive bankAccount bankAccount defaultAccount; // Initialize bankAccount defaultAccount; // Initialize bankAccount anAcct("Bob", 50.00); // Initialize bankAccount anAcct("Bob", 50.00); // Initialize anAcct.withdraw(20.00); // Modify anAcct.withdraw(20.00); // Modify anAcct.deposit(40.00); // Modify anAcct.deposit(40.00); // Modify cout << anAcct.name() << endl; // Access cout << anAcct.name() << endl; // Access cout << anAcct.balance() << endl; // Access cout << anAcct.balance() << endl; // Access return 0; return 0;}

15 6-15 6.6.2 Constructors  The first two function headings for bankAccount differs from the other members  they have no return type  they have the same name as the class  These are the constructor functions  create three default bankAccount objects: bankAccount a, b, c; bankAccount a, b, c;  initialize one initialized instance of the class: bankAccount anAcct("Bob", 123.45); bankAccount anAcct("Bob", 123.45);

16 6-16 Constructors continued  Other constructor messages: string s1, s2, s3; string s1, s2, s3; string name("First I. L. Last"); string name("First I. L. Last"); bankAccount a1, a2, a3; bankAccount a1, a2, a3; bankAccount anotherAcct("CH1234", 5678.90); bankAccount anotherAcct("CH1234", 5678.90);  General form for object construction: class-name object-name-list ; class-name object-name-list ;-or- class-name object-name ( initial-state ) ; class-name object-name ( initial-state ) ;

17 6-17 6.3 The State Object Pattern  Many classes have these things in common  private data members store the state of objects  constructors initialize private data members  modifiers alter the private data members  accessors allow us to inspect the current state of an object or to have its state available in expressions

18 6-18 Object Pattern  An object pattern is a guide for designing and implementing new classes  The state object pattern describes objects that Maintain a body of data and provide suitable access to it by other objects and human users  Object patterns help us understand new objects  The state object pattern summarizes many of the classes you will implement at first

19 6-19 Pattern:State Object Problem: Maintain a body of data and provide suitable access to it by other object and human users class { Outline: class a-descriptive-class-name {public: // default state default-constructor // default state constructors(initial-state) modifying-functions accessing-functionsprivate: // the state data-members // the state};

20 6-20 6.3.1 Using Constructors, Modifiers, and Accessors  Constructors initialize the state of an object: string s2("initial string"); // State of s2 is "initial string" string aDefaultString; // State of aDefaultString is "" bankAccount anAcct("Early Grey", 2150.67); // Early Grey has a starting balance of 2,150.67 bankAccount aDefaultAccount; // aDefaultAccount.name() would return "?name?" // and aDefaultAccount.balance() would return 0.0

21 6-21 Using Modifiers  Modifiers alter the state of an object: string s2("initial string"); string s2("initial string"); s2.replace(1, 3, "NEW"); s2.replace(1, 3, "NEW"); // s2 is "iNEWial string" // s2 is "iNEWial string" aGrid.move(5); aGrid.move(5); // The mover is 5 spaces forward // The mover is 5 spaces forward anAccount.withdraw(120.00) anAccount.withdraw(120.00) // Balance is reduced by 120.00 // Balance is reduced by 120.00

22 6-22 Using Accessors  Accessors either return the current value of an object's data member, or return some information related to the state of an object: s2.length() // Return the dynamic length s2.length() // Return the dynamic length g.row() // Tell me where the mover is g.row() // Tell me where the mover is g.column() g.column() myAccount.balance()// Get current balance myAccount.balance()// Get current balance aBook.borrower() // who has the book aBook.borrower() // who has the book s2.substr(0, 3) // A piece of the string s2.substr(0, 3) // A piece of the string

23 6-23 Naming Conventions  Rules #1, 2, and 3: 1: Always use meaningful names 2: Always use meaningful names 3: Always use meaningful names  Rule #4 Constuctors:Name of the class Modifiers:Verbs borrowBook withdraw Accessors:Nouns length row nRows  could use getLength, getRow, getnRows

24 6-24 6.4 public: or private:  When designing a class, do this at least for now  place operations under public:  place object that store state under private:  Public messages can be sent from the block in which the object is declared  Private state can not be messed up like this bankAccount myAcct("Me", 10.00); bankAccount myAcct("Me", 10.00); myAcct.my_balance = myAcct.my_balance + 999999.99; myAcct.my_balance = myAcct.my_balance + 999999.99; //... //...

25 6-25 Protecting an Object's State  Access modes make operations available to clients and also protect the state  The scope of members is as follows: Access ModeWhere is the member known? scope public: In all class member functions and in the block of the client code where the object has been declared in main for instance private: Only to class members functions.

26 6-26 Why is the state private?  Recommendations:  consistently declare operations after public:  and data members after private:  A public operation can be used by the client  private data avoids direct access to state: myAccount.my_balance = 1000000.00; myAccount.my_balance = 1000000.00;  Now, to modify the state, we must go through the proper channels--deposit.

27 6-27 Another State Object Example class student { public://--constructors student(); student(); student(string initName, student(string initName, double initCredits, double initCredits, double initQualityPoints); double initQualityPoints); // --modifier(s) void set_name(string newName); void set_name(string newName); void recordCourse(double credits, void recordCourse(double credits, double numericGrade); double numericGrade); // --accessor(s) double GPA() const; double GPA() const; string name() const; string name() const;private: string my_name; // ID string my_name; // ID double my_credits; // credits completed double my_credits; // credits completed double my_QualityPoints; // sum of credits*grades double my_QualityPoints; // sum of credits*grades};

28 6-28 Active Learning  Class name ______________?  Operations names _______________?  Names of objects that store state _____________?  # arguments for recordCourse ____________?  Return type of GPA _____________?  # arguments for GPA ____________?  Write code that initializes one student object records two courses and shows the GPA elsewhere  What value is returned for your student ? ____?

29 6-29 6.4.1 Separating Interface from Implementation  Class definitions are usually stored in.h files  The implementations of those member functions are usually stored in.cpp files  Separating interface from implementation is a sound software engineering principle  But to construct objects when the class is in two separate files requires some extra work  or the little "trick" on the next slide

30 6-30 Keeping things simple but not traditional to save compile time  Most author-supplied classes have 3 files  The file name with no dot '.' #includes both the class definition and the member function implementations automatically: // File name: baccount #ifndef _BACCOUNT_ // These safeguards prevent #define _BACCOUNT_ // duplicate compilation #include "baccount.h" // class bankAccount definition #include "baccount.cpp" // function implementation #endif

31 6-31 6.5 Implementing Class Member Functions  Class member function implementation are similar to their non-member counterparts  All class member functions must be qualified with the class name and :: resolution operator void bankAccount::withdraw(double amount) void bankAccount::withdraw(double amount) { // This function can reference private data! // This function can reference private data! }  constructors cannot have a return type bankAccount::bankAccount(string initName, bankAccount::bankAccount(string initName, double initBalance) double initBalance)

32 6-32 6.5.1 Implementing Constructors  The following default constructor (no arguments) bankAccount::bankAccount() bankAccount::bankAccount() { my_name = "?name?"; my_name = "?name?"; my_balance = 0.0; my_balance = 0.0; } is called three times with this code: bankAccount a1, a2, a3; bankAccount a1, a2, a3;  Each has the same default state. output: ?__________? cout << a1.name() << a2.name() << a3.name(); cout << a1.name() << a2.name() << a3.name(); cout << a1.balance() << a2.balance() cout << a1.balance() << a2.balance() << a3.balance(); << a3.balance();

33 6-33 Constructors with parameters  The following constructor with parameters bankAccount::bankAccount(string initName, bankAccount::bankAccount(string initName, double initBalance) double initBalance) { my_name = initName; my_name = initName; my_balance = initBalance; my_balance = initBalance; } is called whenever bankAccount objects are constructed with arguments like this: is called whenever bankAccount objects are constructed with arguments like this: bankAccount initialized("Glass", 2500.00); bankAccount initialized("Glass", 2500.00); bankAccount another("Dunham", 100.00); bankAccount another("Dunham", 100.00);

34 6-34 6.5.2 Implementing Modifiers  Modifying functions are implemented like non members except they must be qualified with class- name ::  This gives the modifier access to the state that is to be modified.  In this example, the private data member my_balance is changed: so do not use const void bankAccount::deposit(double depositAmount) void bankAccount::deposit(double depositAmount) { // post: my_balance has depositAmount added { // post: my_balance has depositAmount added my_balance = my_balance + depositAmount; my_balance = my_balance + depositAmount; }

35 6-35 6.5.3 Implementing Accessors:  Accessor functions must also be qualified with class-name :: to gives access to the state to being used to return info. remember to write const double bankAccount::balance() const double bankAccount::balance() const { // no processing is necessary. Just return it. { // no processing is necessary. Just return it. return my_balance; return my_balance; }  In this example, the private data member my_balance is made available like this: cout << anAcct.balance() << endl; cout << anAcct.balance() << endl;

36 6-36 6.6 Object-Oriented Design Heuristics  Classes must be designed  There are some heuristics (guidelines) to help us make design decisions Design Heuristic 6-1 Design Heuristic 6-1 All data should be hidden within its class All data should be hidden within its class  Ramifications:  Good: Can't mess up the state (compiler complains)  Good: Have to create interface of member functions  Bad: Extra coding, but worth it

37 6-37 6.6.1 Cohesion Within a Class  A class definition provides the public interface-- messages should be closely related  The related data objects necessary to carry out a message should be in the class Design Heuristic 6-2 Keep related data and behavior in one place Keep related data and behavior in one place  Ramifications  Good: Provides intuitive collection of operations  Good: Reduces the number of arguments in messages  Bad: None that I can think of

38 6-38 Cohesion continued  For example, cohesion means  the bankAccount class does not have operations like dealCardDeck or ambientTemperature  the bankAccount class has access to the balance, something which often needs to be referenced.  The balance (named my_balance ) is not maintained separately or passed as an argument

39 6-39 Cohesion continued  Synonyms for cohesion:  hanging together  unity, adherence, solidarity  Cohesion means  data objects are related to the operations  operations are related to the data objects  data and operations are part of the same class definition

40 6-40 6.6.2 Why are Accessors const and Modifiers not?  Have you noticed that const follows all accessing functions? but not any others  It necessary to make our new classes behave like the standard classes  specifically, it is necessary to allow objects passed by const reference to behave correctly  such parameters should allow the accessing messages to be sent, but not any modifing message

41 6-41 const messages okay, all others are not void display(const bankAccount & b) { // OKAY to send name and balance messages since they // OKAY to send name and balance messages since they // were both declared with const member functions // were both declared with const member functions cout << "{ bankAccount: " << b.name() cout << "{ bankAccount: " << b.name() << ", $" << b.balance() << " }" << endl; << ", $" << b.balance() << " }" << endl; // Modifying message to non-const member function // Modifying message to non-const member function // was not tagged as const. It should be an ERROR // was not tagged as const. It should be an ERROR b.withdraw(234.56); b.withdraw(234.56);}  Note: Turbo/Borland C++ reduces the error to a warning. This is not good.

42 6-42 A C++ specific heuristic  This leads to another guideline that is particular to C++ Design Heuristic 6-3 Design Heuristic 6-3 Always declare accessor member functions as Always declare accessor member functions as const. Never declare modifiers as const const. Never declare modifiers as const  This guideline is easy to forget  Unless you thoroughly test, you may not get a compiletime error.  You will not be told something is wrong until you try to pass an instance of your new class by const reference.

43 6-43 Forgetting const == compiletime error message  The programming projects ask you to implement member functions  the class definition is given  If the class definition has const, you must write const in the member function implementation also ERROR: overloaded member function not found in 'X' ERROR: overloaded member function not found in 'X' // file X.h // file X.h class X { int foo() const; int foo() const; …}; // file X.cpp headings must match! // file X.cpp headings must match! int foo() { …}


Download ppt "6-1 Computing Fundamentals with C++ Object-Oriented Programming and Design, 2nd Edition Rick Mercer Franklin, Beedle & Associates, 1999 Presentation Copyright."

Similar presentations


Ads by Google