5 Feb 1996

Outline

Notes:  1) We will be handing out a copy of last year's quiz tomorrow.
           Note that we're further along this year because we didn't
           spend as much time covering C.
        2) The handout on C++ Basics, Part 2 gives a pretty good explanation
           of classes.

A complex number class

First, we need to select a representation.  There are two obvious choices:

  1.  Store the real and imaginary components, both doubles.
  2.  Store the magnitude and angle, both doubles.

Let's pick (1), but keep that private.

/* the class definition belongs in a header file, say Complex.h */

class Complex{
   /* we'll see what this means in a moment */
   friend Complex product(Complex num1, Complex num2);
public:
   Complex(double r=0.0, double i=0.0); // constructor, allows initialization
   double magnitude();
   double angle();
   double real_part();
   double imaginary_part();
private:
   double real;      // real component of number
   double imaginary; // imaginary component of number
};

/* member functions belong in file Complex.c, listed below */

#include <iostream.h>
#include <math.h>
#include "Complex.h"

/* the following function constructs a complex number */

Complex::Complex(double r, double i){
   real = r;
   imaginary = i;
};

   /* Complex numbers can now be created as follows: */

   Complex new_num(1.0,-3.1);    // new_num has been initialized
   Complex new_num2;             // new_num2 initialized to (0.0,0.0)

/* the following functions return the real and imaginary parts */

double Complex::real_part(){
   return real;
};

double Complex::imaginary_part(){
   return imaginary;
};

/* Why don't these functions take arguments?  They are used as follows: */

   cout << "The real part is " << new_num.real_part() << endl;

   /* (This should print 1.0.) */

/* the following functions need math.h */

double Complex::magnitude(){
   return sqrt((real*real)+(imaginary*imaginary));
};

double Complex::angle(){
   return atan2(real,imaginary);
};

/* These two functions are not member functions. */

Complex sum(Complex num1, Complex num2){
   Complex result(num1.real_part()+num2.real_part(),
                  num1.imaginary_part()+num2.imaginary_part());
   return result;
};

/* We could make these functions a little faster & simpler if we made */
/* them friends of the Complex class.  (See class definition.)        */

Complex product(Complex num1, Complex num2){
   Complex result;
   result.real = (num1.real*num2.real)-(num1.imaginary*num2.imaginary);
   result.imaginary = (num1.real*num2.imaginary)+(num1.imaginary*num2.real);
   return result;
};

   /* Some examples. */

   Complex a(5.0,-32.4);
   cout << "Angle: " << a.angle() << " Magnitude: " << a.magnitude() << endl;
   Complex b(1.0,1.2);
   Complex c;
   c = sum(product(a,b),a);        /* i.e., c = (a*b)+a */
   cout << "(" << c.real_part() << "," << c.imaginary_part() << ")" << endl;

A stack class

/*
 * Stack abstract data type.  Empty Stack is represented by top = NULL.
 */
struct S_element {
    int data;
    struct S_element * next;
};

class Stack{
public:
   Stack();  // constructor
   ~Stack(); // destructor
   int is_empty();
   int pop();
   void push(int data);
private:
   S_element *top;
};


/*
 * Constructor
 */
Stack::Stack(void) {
    top = NULL;
}

/*
 * is_empty returns TRUE if the stack is empty.
 */
int Stack::is_empty(Stack * s) {
    return (s->top == NULL);
}

/*
 * Stack::pop removes the top of the stack from the stack, and 
 * returns the value of element just popped.
 */
int Stack::pop() {
    int data;
    S_element *next;
    if (top == NULL) {
    cerr << "Attempt to pop from an empty Stack." << endl;
    return 0;
    }
    data = top->data;
    next = top->next;
    delete top;
    top = next;
    return data;
}

/*
 * Stack::push pushes the given data onto the given stack
 */
void Stack::push(int data) {
    S_element * newtop;
    newtop = new S_element;
    newtop->data = data;
    newtop->next = top;
    top = newtop;
}

/*
 * Destructor (frees the entire stack)
 */
void Stack::~Stack() {
    S_element *elt, *eltx;
    for (elt = top; elt != NULL; elt = eltx) {
    eltx = elt->next;
    /* below we can do anything we want with the current element elt  */
    /* we are not depending on any of its fields to continue the loop */
    delete elt;
    }
}