SDSU 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

  1. Class
    1. Class with Operations
    2. Class Members
    3. Combining Classes
    4. Classes and Files: Style Considerations
    5. Classes and Parameters
    6. Pointers to Objects
    7. Const and Functions
    8. Categorizing Function Members by Usage

Class

( 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;
}

Class with Operations

#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;
}

Class Members



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

Combining Classes

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";
}

Classes and Files: Style Considerations


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


Classes and Parameters

#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;
}

Pointers to Objects

#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

Const and Functions

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 );

}

Categorizing Function Members by Usage


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 ];	}