CS 596 OODP
C++ Classes Part A
[To Lecture Notes Index]
San Diego State University -- This page last updated Sept. 5, 1995

Contents of C++ Classes Part A Lecture
- Class
- Class with Operations
- Class Members
- Combining Classes
- Classes and Files: Style Considerations
- Classes and Parameters
- Pointers to Objects
- Const and Functions
- Categorizing Function Members by Usage
( Module )( Package )As a Record or Struct
#include <iostream.h>
class BankAccount // class head
{ // class body
public :
float balance;
};
int main()
{
BankAccount customer;
customer.balance = 2.0;
cout << customer.balance << "\n";
return 0;
}
Output
2
Second Example
#include <iostream.h>
class StudentRecord
{
public :
char firstName[ 20 ];
char lastName[ 30 ];
float grade;
char address[ 100 ];
};
int main()
{
StudentRecord good;
StudentRecord bad;
StudentRecord cs320[ 40 ];
good.firstName[0] = 'R'; // Where is null terminator?
good.lastName[0] = 'W';
good.address[0] = 'S';
good.grade = 4.0;
bad = good; // copies the record
cs320[ 0 ] = good;
cs320[ 1 ].address[0] = 'A';
return 0;
}
#include <iostream.h>
class Stack
{
public:
void push( int item );
float pop();
float stackElements[ 100 ];
int topOfStack;
};
void Stack :: push( int item )
{
stackElements[ topOfStack++ ] = item;
}
float Stack :: pop()
{
return stackElements[ --topOfStack ];
}
main() {
Stack TreeLinks; // TreeLinks, Nodes, Papers are
Stack Nodes, Papers; // Stack objects
TreeLinks.topOfStack = 0;
Nodes.topOfStack = 0;
TreeLinks.push( 5.0 );
Nodes.push( 3.3 );
TreeLinks.push( 9.9 );
cout << TreeLinks.pop() << endl;
}
Why Not Struct?
#include <iostream.h>
struct Stack
{
float stackElements[ 100 ];
int topOfStack;
};
void push( Stack& it, int item )
{
it.stackElements[ ( it.topOfStack )++ ] = item;
}
float pop( Stack& it )
{
return it.stackElements[ --( it.topOfStack ) ];
}
int main()
{
Stack TreeLinks; // TreeLinks, Nodes, Papers are
Stack Nodes, Papers; // Stack objects
TreeLinks.topOfStack = 0;
Nodes.topOfStack = 0;
push( TreeLinks, 5.0 );
push( Nodes, 3.3 );
push( TreeLinks, 9.9 );
cout << pop( TreeLinks ) << endl;
return 0;
}
Abstraction - Data Type
- What is it?
- What does the data type have to know in order to accomplish its tasks?
-
- What are the tasks?
Information Hiding
- How much of the information and how many of the operations can I
hide?
class Stack
{
public:
Stack();
int isEmpty();
int isFull();
void push( int item );
float pop();
private:
float stackElements[ 100 ];
int topOfStack;
};
Stack :: Stack() // Constructor
{
topOfStack = 0;
}
int Stack :: isEmpty()
{
if ( topOfStack == 0 ) return 1;
else return 0;
}
int Stack :: isFull() // This needs work
{
if ( topOfStack == 100 ) return 1;
else return 0;}
void Stack :: push( int item )
{ stackElements[ topOfStack++ ] = item; }
float Stack :: pop()
{ return stackElements[ --topOfStack ]; }
Using Stack
int main()
{
int X; // No op statement at runtime
Stack TreeLinks; // calls Stack :: Stack() on TreeLinks
TreeLinks.push( 5.0 );
Stack Nodes; // calls Stack :: Stack() on Nodes
Nodes.push( 3.3 );
TreeLinks.push( 9.9 );
cout << TreeLinks.pop() << endl;
return 0;
}
Recall:
Stack :: Stack()
{
topOfStack = 0;
}
Data members
Member Functions
Public member accessible from inside and outside class
Private member accessible from inside class only
Protected member public to derived class, private to others
public interface public member functions
class Stack
{
public:
Stack();
int isEmpty();
int isFull();
void push( int item );
float pop();
private:
float stackElements[ 100 ];
int topOfStack;
};
Private and Public
#include <iostream.h>
class BankAccount
{
public:
void setBalance( float amount );
float getBalance();
private:
float balance;
};
void BankAccount :: setBalance( float amount )
{
balance = amount;
}
float BankAccount :: getBalance()
{
return balance;
}
int main()
{
BankAccount customer;
customer.setBalance( 2.0 );
cout << customer.getBalance() << "\n";
return 0;
}
Accessing Function Members
#include <iostream.h>
class BankAccount
{
public:
void setBalance( float amount );
float getBalance();
private:
float balance;
float PayTaxes( float TaxableAmount );
};
void BankAccount :: setBalance( float amount )
{
balance = PayTaxes( amount );
}
float BankAccount :: getBalance()
{
return balance;
}
float BankAccount :: PayTaxes( float TaxableAmount )
{
return TaxableAmount*0.70;
}
int main() {
BankAccount customer;
customer.setBalance( 2.0 );
return 0;
}
Interface Specification
class BankAccount
{
public:
void setBalance( float ); // Don't need the parameter name
float getBalance();
private:
float balance;
float PayTaxes( float ); // Don't need the parameter name
};
void BankAccount :: setBalance( float amount ) //Need the name here
{
balance = PayTaxes( amount );
}
float BankAccount :: getBalance()
{
return balance;
}
float BankAccount :: PayTaxes( float TaxableAmount )
{
return TaxableAmount*0.70;
}
class Stack
{
public:
Stack(); void push( int item );
int isEmpty(); float pop();
int isFull();
private:
float stackElements[ 100 ]; int topOfStack;
}; //Implementation of stack not shown
class BankAccount
{
public:
void setBalance( float amount ); float getBalance();
private:
float balance;
Stack history;
};
void BankAccount :: setBalance( float amount )
{
balance = amount;
history.push( amount );
}
float BankAccount :: getBalance()
{ return balance; }
main() {
BankAccount customer;
Stack requests;
customer.setBalance( 2.0 );
cout << customer.getBalance() << "\n";
}
Each class requires at least two files:
file for class definition
file( s ) for implementation of class function members
Header file for class definition
// File: bankAccount.hh
// Created: Sunday, Nov. 1, 1992, 3:05 PM
// Author: Roger Whitney
// Copyright ( c ) 1992 by SDSU
#ifndef _bankAccount_HH
#define _bankAccount_HH
#ident "This line is used by SCCS for version control"
// Defines the interface to the BankAccount class
class BankAccount
{
public:
void setBalance( float amount );
float getBalance();
private:
float balance;
};
#endif // _bankAccount_HH
Classes and Files: Style ConsiderationsContinued
File for class Implementation
// File: bankAccount.cc
// Created: Sunday, Nov. 1, 1992, 3:11 PM
// Author: Roger Whitney
// Copyright ( c ) 1992 by SDSU
#ident "This line is used by SCCS for version control"
#include "backAccount.hh"
// Implementation of BankAccount
void BankAccount :: setBalance( float amount )
{
balance = amount;
}
float BankAccount :: getBalance()
{
return balance;
}
Classes and Files: Style ConsiderationsContinued
File for main program
// Standard Comment line deleted to save space
#include "bankAccount.hh"
#include <iostream.h>
// Sample program using bankAccount class
int main()
{
BankAccount customer;
customer.setBalance( 2.0 );
cout << customer.getBalance() << endl;
return 0;
}
Sample makefile
test: bankAccount.o main.c
CC bankAccount.o main.cc -o test
bankAccount.o: bankAccount.hh bankAccount.cc
CC bankAccount.cc -c
clean:
rm *.o
#include <iostream.h>
class BankAccount
{
public:
void setBalance( float amount );
float getBalance();
private:
float balance;
};
void BankAccount :: setBalance( float amount )
{ balance = amount; }
float BankAccount :: getBalance()
{ return balance; }
void WinLottery( BankAccount winner )
{
winner.setBalance( 10000.0 );
}
int main() {
BankAccount customer;
customer.setBalance( 2.0 );
WinLottery( customer );
cout << customer.getBalance() << "\n";
return 0;
}
#include <iostream.h>
class BankAccount
{
public:
void setBalance( float amount );
float getBalance();
float balance;
};
void BankAccount :: setBalance( float amount )
{ balance = amount; }
float BankAccount :: getBalance()
{ return balance; }
main()
{ BankAccount* customer;
customer = new BankAccount;
customer->balance = 20;
(*customer).balance = 10;
customer->setBalance( 50 );
(*customer).setBalance( 23 );
cout << customer->balance << "\n";
}
Classes and Parameters
Done Correctly
void WinLottery( BankAccount* winner )
{
winner->setBalance( 10000.0 );
}
void WinLottery( BankAccount& winner )
{
winner.setBalance( 10000.0 );
}
Pass-by-value and return-by-value
Costly on large items
Coping objects can be very expensive
Can have odd side effects on objects
Pass-by-reference and return-by-reference
Fast
Allows side effects
Eliminating Side Effects
#include <iostream.h>
int SideEffectsSum( int A[ ], int B[ ] )
{
A[ 0 ] = A[ 0 ] + 10;
return A[ 1 ] + B[ 2 ];
}
int PlayItSafeSum( const int A[ ], const int B[ ] )
{
return A[ 1 ] + B[ 2 ];
}
int NoWayDudeSum( const int A[ ], const int B[ ] )
{
A[ 0 ] = A[ 0 ] + 10; // Compile Error
return A[ 1 ] + B[ 2 ];
}
main()
{
int X[ ] = {1, 2, 3};
int Y[ ] = {4, 5, 6};
cout << SideEffectsSum( X, X ) << "\t" << X[ 0 ] << endl;
cout << PlayItSafeSum( Y, Y ) << "\t" << Y[ 0 ] << endl;
}
Const and Classes
#include <iostream.h>
class BeCareful {
public:
int here;
void NotSafe();
void Safe();
};
void BeCareful :: NotSafe() {
here = here + 5;
cout << here << endl;
}
void BeCareful :: Safe() {
cout << here << endl;
}
void TestIt( const BeCareful& WithThis ) {
WithThis.NotSafe(); // Compile Error
WithThis.Safe(); // Compile Error
}
main() {
BeCareful WithMe;
WithMe.here = 1;
TestIt( WithMe );
}
Const and Classes
#include <iostream.h>
class BeCareful {
public:
int here;
void NotSafe();
void Safe() const;
};
void BeCareful :: NotSafe() {
here = here + 5;
cout << here << endl;
}
void BeCareful :: Safe() const {
cout << here << endl;
}
void TestIt( const BeCareful& WithThis ) {
WithThis.NotSafe(); // Compile Error
WithThis.Safe(); // This is ok
}
main() {
BeCareful WithMe;
WithMe.here = 1;
TestIt( WithMe );
}
Const and Classes
No Cheating
#include <iostream.h>
class BeCareful {
public:
int here;
void NotSafe() const;
void Safe() const;
};
void BeCareful :: NotSafe() const {
here = here + 5; // Compile Error
cout << here << endl;
}
void BeCareful :: Safe() const {
cout << here << endl;
}
void TestIt( const BeCareful& WithThis ) {
WithThis.NotSafe();
WithThis.Safe(); // This is ok
}
main() {
BeCareful WithMe;
WithMe.here = 1;
TestIt( WithMe );
}
Const and Classes
Really, No Cheating
#include <iostream.h>
class Foo {
public:
int where;
void setWhere( int x );
};
void Foo :: setWhere( int x )
{
where = x;
}
class BeCareful {
public:
int here;
Foo you;
void NotSafe();
void Safe() const;
};
void BeCareful :: NotSafe() {
you.setWhere( 4 );
}
void BeCareful :: Safe() const {
NotSafe(); // Compile error
}
void TestIt( const BeCareful& WithThis ) {
WithThis.Safe();
}
Const and Classes
Well, you can cheat, But don't
#include <iostream.h>
class BeCareful {
public:
int* here;
BeCareful();
void NotSafe() const;
void Safe() const;
};
BeCareful :: BeCareful() { here = new int( 5 ); };
void BeCareful :: NotSafe() const{
*here = *here + 5; // OK????
cout << *here << endl;
}
void BeCareful :: Safe() const{
cout << *here << endl;
}
void TestIt( const BeCareful& WithThis ) {
WithThis.NotSafe(); // This works
WithThis.Safe(); // This is ok
}
main() {
BeCareful WithMe;
TestIt( WithMe );
}
Modifier
Alters the state of an object
Selector (Access)
Accesses the state of an object
Does not alter the state
Iterator
Accesses all parts of an object in well-defined order
Used on collections: arrays, lists, sets, etc.
Constructor (Manager)
Creates an object and/or initializes its state
Destructor (Manager)
Frees the state of an object and/or destroys the object
class Stack
{
public:
Stack(); // Constructor
int isEmpty() const; // Selector
int isFull() const; // Selector
void push(int item); // Modifier
float pop(); // Modifier
private:
float stack[ 100 ];
int topOfStack;
};
Stack::Stack()
{
topOfStack = 0;
}
int Stack::isEmpty()
{
if ( topOfStack == 0 ) return 1;
else return 0;
}
int Stack::isFull()
{
if ( topOfStack == 100 ) return 1;
else return 0;
}
void Stack :: push( int item )
{ stack[ topOfStack++ ] = item; }
float Stack::pop()
{ return stack[ --topOfStack ]; }