C++ Lecture 5

[Previous Lecture] [Lecture Index] [Next Lecture]

Objective of (OO) Design

Problems are complex because: Problem solved by Possible Bonus: more likely to create re-usable code

Example Problem

Write a program that simulates the transport system in a factory. The transport system consists of segments of fixed track called `channels' which are always parallel to the X-axis, `shuttles' which move on the channels, stretches of fixed track called `rails' which are always parallel to the Y-axis, and groups of moving channels called `magazines' which move on the rails. Each channel has one or more motors: the motors drive a gear which, in turn, will move a shuttle that is under the gear. Each magazine has a motor which moves it along the rails. Motors have two control lines: one that causes the motor to turn forwards, and one that causes it to move backwards. They also have a `tooth sensor' output line: the line is high when a tooth of the gear is over the sensor. Each motor is connected to a common interface bus, and has a unique bus address.

Given a factory layout and a set of bus inputs (and an associated time for each input), the program is to


Class Inheritance


shapes.h

#ifndef SHAPES_H
# define SHAPES_H

class Shape {
  public:
    Shape();
    virtual void move(int dx, int dy) = 0;
    virtual void draw(Display &d) = 0;
    virtual ~Shape();
};

class Circle : public Shape {
  public:
    Circle(const Point &center, int radius);
    void move(int dx, int dy);
    void draw(Display &d);
  private:
    Point center;
    int radius;
};

class Rectangle : public Shape {
  public:
    Rectangle(const Point &ul, const Point &lr);
    void move(int dx, int dy);
    void draw(Display &d);
  protected:
    Point upperLeft;
    Point lowerRight;
};

class GridRectangle : public Rectangle {
  public:
    GridRectangle(const Point &ul, const Point &lr, int sep);
    void draw(Display &d);
  protected:
    int gridSep;
};

class Picture : public Shape {
  public:
    Picture(int nElem);
    bool setElement(int index, Shape *s);
    void move(int dx, int dy);
    void draw(Display &d);
    ~Picture();
  private:
    int nElements;
    Shape **elements;
};

#endif /* SHAPES_H */

display.h

#ifndef DISPLAY_H
#define DISPLAY_H

class Display {
  public:
    Display();
    ~Display();
    void drawLine(const Point &from,
                  const Point &to);
    void update();
};

#endif /* DISPLAY_H */

shapes.cc

#include <iostream.h>
#include "point.h"
#include "display.h"
#include "shapes.h"

// Shape class

Shape::Shape()
{
}

Shape::~Shape()
{
}


// Circle class

Circle::Circle(const Point &center, int radius)
    : center(center), radius(radius)
{
}

void
Circle::move(int dx, int dy)
{
    center.move(dx, dy);
}

void
Circle::draw(Display &d)
{
    // ...
}

// Rectangle class

Rectangle::Rectangle(const Point &ul,
                     const Point &lr)
    : upperLeft(ul), lowerRight(lr)
{
}

void
Rectangle::move(int dx, int dy)
{
    upperLeft.move(dx, dy);
    lowerRight.move(dx, dy);
}

void
Rectangle::draw(Display &d)
{
    Point ur(lowerRight.getX(),
             upperLeft.getY());
    Point ll(upperLeft.getX(),
             lowerRight.getY());
    d.drawLine(upperLeft, ur);
    d.drawLine(ur, lowerRight);
    d.drawLine(lowerRight, ll);
    d.drawLine(ll, upperLeft);
}

// Grid rectangle class

GridRectangle::GridRectangle(const Point &ul,
                             const Point &lr,
                             int sep)
    : Rectangle(ul, lr), gridSep(sep)
{
}

void
GridRectangle::draw(Display &d)
{
    // Draw outline
    Rectangle::draw(d);

    // Draw vertical grid lines
    for (int x = upperLeft.getX() + gridSep / 2
         ; x < lowerRight.getX(); x += gridSep)
    {
        Point p1(x, upperLeft.getY());
        Point p2(x, lowerRight.getY());
        d.drawLine(p1, p2);
    }
    // Draw horizontal grid lines
    for (int y = upperLeft.getY() + gridSep / 2
         ; y < lowerRight.getY(); y += gridSep)
    {
        Point p1(upperLeft.getX(), y);
        Point p2(lowerRight.getX(), y);
        d.drawLine(p1, p2);
    }
}

// Picture class

Picture::Picture(int nElem)
    : nElements(nElem)
{
    elements = new Shape *[nElements];
    int i;

    for (i = 0; i < nElements; i++)
        elements[i] = 0;
}

void
Picture::draw(Display &d)
{
    int i;

    for (i = 0; i < nElements; i++)
	if (elements[i])
	    elements[i]->draw(d);
}

void
Picture::move(int dx, int dy)
{
    int i;

    for (i = 0; i < nElements; i++)
	if (elements[i])
	    elements[i]->move(dx, dy);
}

bool
Picture::setElement(int index, Shape *s)
{
    if (index < 0 || index >= nElements)
        return false;
    elements[index] = s;
    return true;
}

Picture::~Picture()
{
    delete[] elements;
}

shapes-main.cc

#include "point.h"
#include "display.h"
#include "shapes.h"

int
main()
{
  Display display;
  Rectangle r(Point(2, 2), Point(6, 4));
  GridRectangle gr(Point(10, 4), Point(16, 9),
                    3);
  Circle c(Point(0, 4), 8);

  Picture subpic(2);
  subpic.setElement(0,
    new Circle(Point(10, 2), 3));
  subpic.setElement(1,
    new Rectangle(Point(7, 5), Point(13, -1)));

  Picture pic(4);

  pic.setElement(0, &r);
  pic.setElement(1, &c);
  pic.setElement(2, &subpic);
  pic.setElement(3, &gr);

  pic.draw(display);

  display.update();

  return 0;
}

More on Inheritance


[Previous Lecture] [Lecture Index] [Next Lecture]