C++ vs. Smalltalk

C++ is...
* Strongly typed: Declare everything, don't mix types
* Compiled: Faster, smaller, less flexible
* Mixed object-oriented and procedural: You can cheat

OOP in C++

* Basics of C in C++ (variables, I/O)
* Declaring classes
* Terminology
* Data hiding: public, private, and protected
* Multiple inheritance
* Looking up functions at run-time: Virtual functions

A simple C++ program

#include <iostream.h>   // Access the runtime

main() {  // Must be main, not MAIN, not Main

	cout << "The volume of the box car is";
	cout << 11 * 9 * 40;
	cout << endl;

}

Declaring variables

#include <iostream.h>
main() {
	int result, height = 11, width = 9;
	int length = 40;
	result = height * width * length;
	cout << "The volume of the box car is"
		<< 11 * 9 * 40 << endl;
}

char                                       character (1 byte)                         
short                                      integer (2 bytes)                          
int                                        integer (4 bytes)                          
long                                       integer (4 bytes)                          
float                                      floating-point number (4 bytes)            
double                                     floating-point number (8 bytes)            
long double                                floating-point number (8 bytes)            
char *                                     strings (array of characters; array =      
                                           pointer)                                   
void                                       typeless                                   
type []                                    An array (a pointer)                       

Handling input as well as output

#include <iostream.h>
main() {
	int height, width, length;
	cout << Please type three integers." << endl;
	cin >> height;
	cin >> width;
	cin >> length;
	cout << "The volume of the box is" <<
	height * width * length << endl;
}

Executing the program

Please type three integers.
11 9 40		<-- You type (spaces separate, return ends input)
The volume of the box is 3960

Declaring classes in C++

#include <iostream.h>
#include <string.h>

class book {
public:
	book(char *, char *, int);
	void show_book(void);
private:
	char title[64];
	char author[64];
	int pages;
};

class catalog_card : public book {
public:
	catalog_card(char *, char *, int, char *, int);
	void show_card(void);
private:
	char catalog[64];
	int checked_out;	// 1 if checked out, otherwise 0
};

Filling in the functions

Constructors

book::book(char *title, char *author, int pages)
{
	strcpy(book::title,title);
	strcpy(book::author,author);
	book::pages = pages;
}

catalog_card::catalog_card(char *title, char *author, int pages, char * catalog, int checked_out) : book(title, author, pages)
{
	strcpy(catalog_card::catalog, catalog);
	catalog_card::checked_out = checked_out;
}

Filling in the functions

void book:show_book(void)
{
	cout << "Title: " << title << endl;
	cout << "Author: " << author << endl;
	cout << "Pages: " << pages << endl;
}

void catalog_card::show_card(void)
{
	show_book();
	cout << "Catalog: " << catalog << endl;
	if (checked_out)
		cout << "Status: Checked out" << endl;
	else
		cout << "Status: Available" << endl;
}

Using our book and catalog_card classes

void main(void)
{
	catalog_card card("Tale of Two Cities","Dickens",1000,"Fiction Row 1",1); // Declaration

card.show_card();
}

Terminology in C++

C++                                                             Smalltalk                                  
Class (But classes aren't objects)                              Class                                      
Object                                                          Object                                     
Class objects or Compound objects                               Instances                                  
Derived class (catalog_card)                                    Subclass                                   
Base class (book)                                               Superclass                                 
Member function (also, method)                                  Method                                     
Overloading or Shadowing                                        Overriding                                 
Member data                                                     Instance variable                          

Data hiding in C++

public                      Anyone can access (data or function) through use of the dot (.) operator.       
private                     No one but the class can access - not even derived classes!                     
protected                   Derived classes and the declaring class can access, but no one else.            

Accessing class members

class person_statistics {
  public:
	int month_of_birth;
	int year_of_birth;
	int married;
	void initialize_ssn(char *); // function protoype
	void show_dob(void) {    // inline member function
		cout << month_of_birth << "/" << year_of_birth << endl;
	};
  private:
	char ssn[12];
	int children;
};

void main(void)
{
	person_statistics guzdial, ericson;
	guzdial.month_of_birth = 9;
	guzdial.year_of_birth = 62;
	guzdial.married = 1;
	guzdial.children = 1;  // DEFECTIVE!!!
	guzdial.show_dob();
}

Smalltalk data hiding in C++ terms


* Instance variables are protected (only class and subclasses can access)

* Methods are public (anyone can access)

Multiple inheritance in C++

Declaring the two base classes

class computer_screen {
  public:
	computer_screen(char *, long, int, int);
	void show_screen(void);
  private:
	char type[32];
	long colors;
	int x_resolution;
	int y_resolution;
};

class mother_board {
  public:
	mother_board(int, int, int);
	void show_mother_board(void);
  private:
	int processor;
	int speed;
	int RAM;
};

Multiple inheritance in C++


Using both base classes in a new derived class



class computer: public computer_screen, public mother_board
{
  public:
	computer(char *, int, float, 
		char*, long, int, 
		int, int, int, int);
	void show_computer(void);
  private:
	char name[64];
	int hard_disk; //size of
	float floppy;
};

Multiple inheritance in C++

Deriving from a base class other than public

class box{
	public: double height, width, length;
	box() {}; //Default constructor
	box (double h, double w, double l) //with arguments
	{height = h; width = w; length =l;};
	double volume ()
	{return height * width * length;}
};

class box_car : public railroad_car, private box {
public: box_car() : box (10.5, 9.5, 40.0){}; // Default constructor
}

Can hide inherited classes

* box_car in this example cannot access box private variables or functions

                              Public derivation             Protected derivation          Private derivation            
Public member function        remains public                becomes protected             becomes private               
Protected member function     remains protected             remains protected             becomes private               
Private member function       remains private               remains private               remains private               

Creating objects at run-time, & allowing for shadowing

First: Let's do it obvious, but wrong

#include <iostream.h>
class railroad_car {
	public:
	void display_short_name() {cout << "rrc";}
};

class box_car: public raiload_car {
	public:
	void display_short_name() {cout << "box";}
};

//..Similar definitions of tank_car, engine, and caboose go here
 //Define raiload car array
railroad_car *train[100];
main() {
	int car_count, type_code, n;

	for (car_count = 0; cin >> type_code; ++car_count)
		if (type_code == 0) train[car_count] = new engine;
		else if (type_code == 1) train[car_count] = new box_car;
		else if (type_code == 2) train[car_count] = new tank_car;
		else if (type_code == 3) train[car_count] = new caboose;
	
	cout << "There are " << car_count 
		<< " cars in the array." << endl;

	for (n=0; n < car_count; ++n) {
		train[n] -> display_short_name();
		cout << endl;
	}
}

Running the wrong version

Input: 0 1 1 2 3
Output:

There are 5 cars in the array.
rrc
rrc
rrc
rrc
rrc

Why didn't each type of car do its own display_short_name?

* Because C++ can't determine the type of each railroad_car at compile time, you must tell it to look them up at run time

Fixing the class declarations

#include <iostream.h>
class railroad_car {
	public:
	virtual void display_short_name() {cout << "rrc";}
};
class box_car: public raiload_car {
	public:
	virtual void display_short_name() {cout << "box";}
};
//..Similar definitions of tank_car, engine, and caboose go here

Input: 0 1 1 2 3
Output:

There are 5 cars in the array.
eng
box
box
tnk
cab

If you never expect to need the base virtual function...


#include <iostream.h>
class railroad_car {
	public:
	virtual void display_short_name()  = 0
};
class box_car: public raiload_car {
	public:
	virtual void display_short_name() {cout << "box";}
};
//..Similar definitions of tank_car, engine, and caboose go here

Other techniques in C++

* Overloading functions & operators
* Constructors and destructors
* Class templates
* Pointers in C/C++
* C++ references

Overloading functions

#include <iostream.h>

int add_values(int a, int b)
{
	return (a + b);
}

int add_values(int a, int b, int c)
{
	return(a + b + c);
}

void main(void)
{cout << "200 + 801=" << add_values (200, 801) << endl;
cout << "100+201+700=" << add_values(100,201,700) << endl;
}

Overloading operators

#include <iostream.h>
#include <string.h>

class string {
  public:
	string(char *); //Constructor
	void operator +(char *);
	void show_string(void);
  private:
	char data[256];
};
string::string(char *str)
{strcpy(data,str);}

void string::operator +(char *str)
{strcat(data,str);}

void string::show_string(void)
{cout << data << endl;}
 void main(void)
{
	string title("CS 2390");
	string name("Modeling and Design");
	title.show_string();
	title + name;
	title.show_string();
}

Constructors and destructors


* Constructor functions run for each object you create

- You load up the initialization parameters any way you want.

* Destructor functions run when an object is discarded (explicitly or at end of program).

- Good time to get rid of connections, free up allocated memory, free up I/O devices.

Class templates

You can even parameterize types


class array{
  public:
	array(int size);
	long sum(void);
	int average_value(void);
	void show_array(void);
	int add_value(int);
  private:
	int *data;
	int size;
	int index;
};

long array::sum(void)
{	long sum=0; int i;
	for (i=0; i< index; i++)
		sum = sum + data[i]; //sum += data[i];
	return(sum);
}

Class templates

template<class T, class T1>
class array{
  public:
	array(int size);
	T1 sum(void);
	T average_value(void);
	void show_array(void);
	int add_value(T);
  private:
	T *data;
	int size;
	int index;};

template<class T, class T1>
T1 array<T, T1>:sum(void)
{
	T1 sum = 0; int i;
	for (i = 0; i < index; i++)
		sum += data[i];
	return(sum);}

Pointers in C/C++

#include <iostream.h>
void show_string(char *string)
{
	while (*string != `/0')
	{
		cout << *string;
		string++;
	}
}
void main(void)
{
	show_string("Hello, World!");
}

Can also be written:

while (*string)
{
	cout << *string;
	string++;
}

Or even:

while (*string)
	cout << *string++;

C++ references (instead of pointers)

* References are not variables: you can't change them, add to them, assign a pointer to a reference, etc.
* They're a second name for a variable. Hopefully, a little safer.

Pointer-way

void swap_values(float *a, float *b)
{
	float temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

C++ references way

#include <iostream.h>
void swap_values(float& a, float& b)
{
	float temp;
	temp = a;
	a = b;
	b = temp;
}
void main(void)
{
	float big = 10000.0;
	float small = 0.00001;
	float& big_alias = big;
	float& small_alias = small;

	swap_valus(big_alias,small_alias);
// swap_value(float& big, float& small);

	cout << "Big:"<<big<<endl;
	cout << "Small:"<<small<<endl;
}