Title: C and ObjectOriented Programming
1C and Object-Oriented Programming Classes and
Objects
2Important Concepts
- Definition of a class
- Interface versus Implementation
- Reading a class header (.h) file
- ifndef, define and endif
- Public versus Private
- Member functions
- constructors, accessors and modifiers
- OOP design guidelines
3The 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 stringsubstr work? Don't need to know
- Abstract level the interface
- Implementation level the algorithms and local
objects in the member functions
4Class Design DecisionsbankAccount
- bankAccount could have had
- more operations
- more state (data) elements
- 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"
5What 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
6Interface 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,
which the collection of available messages, which
in C is the class definition see next slide
7Class Definition
- class class-name
-
- public
- class-name() //
Default constructor - class-name(parameter-list) // Constructor
with parameters - function-heading //
Members that modify state - function-heading
- function-heading const // Members
that do not modify state - function-heading const
- private
- object-declaration // Data
members -- the state - object-declaration
-
8Class DefinitionsAn example with comments
- class bankAccount
- public
- bankAccount()
- // post construct a default bankAccount object
- bankAccount(string initName, double
initBalance) - // post Initialize bankAccount object with 2
arguments - void deposit(double depositAmount)
- // pre depositAmount gt 0.00
- // post credit depositAmount to this object's
balance - void withdraw(double withdrawalAmount)
- // pre 0 lt withdrawalAmount lt balance
- // postdebit withdrawalAmount from object's
balance - double balance() const
- // post return this object's current account
balance - string name() const
- // post return this object's identification
name - private
- string my_name // The unique account
identification - double my_balance // Stores the current
balance
9Class Definitionscontinued
- 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
10Class Definitionscontinued
- 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
11Objects 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
12The same class without pre and post conditions
code oriented
- class bankAccount
- public // OPERATIONS
- //--constructors
- bankAccount()
- bankAccount(string initName, double
initBalance) - //--modifiers
- void deposit(double depositAmount)
- void withdraw(double withdrawalAmount)
- //--accessors
- double balance() const
- string name() const
- private // STATE
- string my_name
- double my_balance
13class diagramsummary of operations and state
14Sample Messages
- include ltiostream.hgt
- include "baccount" // for class bankAccount
- int main()
- // Test drive bankAccount
- bankAccount defaultAccount //
Initialize - bankAccount anAcct("Bob", 50.00) //
Iinitialize - anAcct.withdraw(20.00) // Modify
- anAcct.deposit(40.00) // Modify
- cout ltlt anAcct.name() ltlt endl // Access
- cout ltlt anAcct.balance() ltlt endl // Access
-
- return 0
15Constructors
- 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
- initialize one initialized instance of the class
- bankAccount anAcct("Bob", 123.45)
16Constructorscontinued
- Other constructor messages
- string s1, s2, s3
- string name("First I. L. Last")
- bankAccount a1, a2, a3
- bankAccount anotherAcct("CH1234", 5678.90)
- General form for object construction
- class-name object-name-list
- -or-
- class-name object-name ( initial-state )
17The 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.
18Object Pattern
- An object pattern is a guide for designing and
implementing new classes - The state object patterns 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- Pattern State Object
- Problem Maintain a body of data and provide
- suitable access to it by other object
- and human users
- Outline class a-descriptive-class-name
- public
- default-constructor // default state
- constructors(initial-state)
- modifying-functions
- accessing-functions
- private
- data-members // the state
-
20Using 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
21Using Modifiers
- Modifiers alter the state of an object
- string s2("initial string")
- s2.replace(1, 3, "NEW")
- // s2 is "iNEWial string"
- aGrid.move(5)
- // The mover is 5 spaces forward
- anAccount.withdraw(120.00)
- // Balance is reduced by 120.00
22Using 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
- g.row() // Tell me where the mover is
- g.column()
- myAccount.balance()// Get current balance
- aBook.borrower() // who has the book
- s2.substr(0, 3) // A piece of the string
23Naming 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
- could use setBorrow, setWithdraw
24public 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)
- myAcct.my_balance myAcct.my_balance
999999.99 - //...
-
25Protecting an Object's State
- Access modes make operations available to clients
and also protect the state. - The scope of members is as follows
- Access Mode Where 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.
26Why 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
- Now, to modify the state, we must go through the
proper channels--deposit.
27Another State Object Example
- class student
- public
- //--constructors
- student()
- student(string initName,
- double initCredits,
- double initQualityPoints)
- // --modifier(s)
- void set_name(string newName)
- void recordCourse(double credits,
- double numericGrade)
- // --accessor(s)
- double GPA() const
- string name() const
- private
- string my_name // ID
- double my_credits // credits completed
- double my_QualityPoints // sum of
creditsgrades
28Separating Interface from Implementation
- The class interface is usually stored in a .h
file - The implementations of those member functions are
usually stored in .cpp file - 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
29Keeping things simple
- Most author-supplied classes have 3 files
- The file name with no dot '.' includes both the
class definition and the member function
implementaitons 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
30Implementing 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 bankAccountwithdraw(double amount)
-
- // This function can reference private data!
-
- Constructors cannot have a return type.
- bankAccountbankAccount(string initName,
- double initBalance)
31Implementing Default Constructors
- The following default constructor (no arguments)
- bankAccountbankAccount()
-
- my_name "?name?"
- my_balance 0.0
-
- is called three times with this code
- bankAccount a1, a2, a3
- Each has the same default state. output
?__________? - cout ltlt a1.name() ltlt a2.name() ltlt a3.name()
- cout ltlt a1.balance() ltlt a2.balance()
- ltlt a3.balance()
32Constructors with Parameters
- The following constructor with parameters
- bankAccountbankAccount(string initName,
- double initBalance)
-
- my_name initName
- my_balance initBalance
-
- is called whenever bankAccount objects are
constructed with arguments like this - bankAccount initialized("Glass", 2500.00)
- bankAccount another("Dunham", 100.00)
33Implementing 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 bankAccountdeposit(double
depositAmount) - // post my_balance has depositAmount added
- my_balance my_balance depositAmount
-
34Implementing Accessor Functions
- 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 bankAccountbalance() const
- // no processing is necessary. Just return
it. - return my_balance
-
- In this example, the private data member
my_balance is made available like this - cout ltlt anAcct.balance() ltlt endl
35Object-Oriented Design Guidelines (Rules)
- Classes must be designed.
- There are some guidelines (heuristics) you can
use to help make design decisions. - Design Guideline
- 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
36Cohesion 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 Guideline
- 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
37Cohesion
- 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
38Cohesion
- 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
39Why 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
40const messages okay, all others are not
- void display(const bankAccount b)
-
- // OKAY to send name and balance messages since
they - // were both declared with const member
functions - cout ltlt " bankAccount " ltlt b.name()
- ltlt ", " ltlt b.balance() ltlt " " ltlt endl
- // Modifying message to non-const member
function - // was not tagged as const. It should be an
ERROR - b.withdraw(234.56)
-
- Note Turbo/Borland C reduces the error to a
warning. This is not good.
41A C Specific Guideline
- This leads to another guideline that is
particular to C - Design Guideline
- Always declare accessor member functions as
const. Never declare modifers as const - This may be difficult to remember
- If you forget it, you may never notice it until
you try to pass an instance of your new class by
const reference.
42Forgetting 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 - ERROR overloaded member function
not found in 'X'
// file X.cpp headings must match! int foo()
// file X.h class X int foo() const