Class Struggle

Class Struggle

By Mike Toms

Overload, 1(1):, April 1993


A basic introduction to the uses of C++

This is a basic introduction to C++ programming. The code example we are going to use is a counter value that appears at a fixed location on the screen, for example the score on a game, a count of the numbers of records processed etc. I know its a trivial example, but it serves well to illustrate the difference in paradigms between C and C++.

The scenario in C.

There are several ways this can be achieved. The first option is to have a general function e.g.

  printat(xpos, ypos, value);

This has the disadvantage of having to remember the X and Y coordinates of where the score is to be printed each time. This can be cured by the second option which is to have the positions of the counter hard wired into the program.

  print_counter(value);

This however, has the obvious disadvantage that when two or more counters are needed, each will have to have its own function, each differing only with the hard wired xpos and ypos values. This can be overcome by setting up a struct containing the xpos, ypos and value and passing the struct to the function. This means that the xpos and ypos values would only need setting once. The whole of the struct can then be passed to the function. This is a better method as we can now have a general function that has all its information tied into one block.

  typedef struct 
{
int xpos;
int ypos;
int value;
} count;
count myscore, computer_score;
myscore.xpos = 10;
myscore.ypos = 10;
myscore.value = 30;
computer_score.xpos = 50;
computer_score.ypos = 10;
computer_score.value = 33;
printat(&myscore);
printat(&compute r_score);
getch();
while (myscore.value++ < 1000)
{
compute r_score.value++;
printat(&myscore);
printat(&computer_score);
}

This has solved the problem of accidentally putting the wrong information at the wrong coordinates etc.

The scenario in C++

In C++, a class would be set up that would contain all the coordinates and the current value, and are manipulated as a whole. Operators can be defined to manipulate the class as if it was a variable in its own right.

Some of this code may not be obvious as to its function, but examine it carefully and then read the annotated code below it.

The header file (counter.h):

  class Counter
{
protected:
int X_Pos;
int Y_Pos;
int CounterValue;
void Display(void);
public:
Counter (int X, int Y, int val = 0);
int operator += (int Val);
int operator ++ (void);
int operator = (int);
friend int& operator = (Counters);
};

The C++ file (counter.cpp):

(Note: those with versions prior to 3.0 will need to use gotoxy and cout in conio.h & iostream.h respectively)

  #include <constream.h>
#include <iomainip.h>
#include "counter.h"

void Counter::Display ()
{
constream console;
console << setxy(X_Pos, Y_Pos)
<< setw(5) << CounterValue;
}

Counter::Counter (int X, int Y, int val)
{
X_Pos = X;
Y_Pos = Y;
CounterValue = val;
Display ();
}

int Counter::operator += (int Val)
{
CounterValue += Val;
Display() ;
return CounterValue;
}

int Counter::operator ++ (void)
{
CounterValue++;
Display();
return CounterValue;
}

int Counter::operator = (int Val)
{
CounterValue = Val;
Display();
return CounterValue;
}

int& operator = (Counter& K) {
return K.CounterValue;
}

The program testcoun.cpp

  #include "counter.h" 

void main(void) {
Counter myscore(10,10),
computer_score(30,10,3);
int  i;
while ((i=myscore)<1000) {
myscore++;
computer_score++;
}
}

Though the definition of a counter class is slightly more long-winded than setting up a struct, I think you will agree that its usage in the main function is much more natural to the C programmer, and it is a lot easier to use in larger programs.

Let's take a look at it in more detail and explain each of the lines. I apologise if this proves to be a little tedious, but it is intended for those without any C programming as well as C programmers.

The class structure of a C++ program is not that dissimilar to a struct in C, but has the addition has the keywords protected, private and public to limit the access to the member items of the class. A class, simply put, is a collection of data items and functions to manipulate those data items.

The general format of a simple class is as follows:

  class <class_name>
{
 private:
<private data & functions)
protected:
<protected data & functions)
public:
 <public data & Junctions)
};

The best way to start designing a class is firstly to decide on the data to be held and then to decide on the member functions that are needed, both internal to the class and the member functions that are visible to functions outside of the class.

We now need to think about several things. Firstly what information do we need to hold? This has already been decided, we need to hold the X and Y positions and the current value that is on the screen. We then need to decide on the level of protection for these items. As none of these items are to be manipulated by anything outside of the class, they can all become either private or protected. Which one selected depends upon if we intend to use this class for inheritance or not. For now we will ignore this possibility and set them to protected.

At this stage our class would look as follows:

  class Counter  // name of the class
{
protected:     // the following items are protected
int X_Pos;  // the xposition of the counter
int Y_Pos;  // the yposition of the counter
int CounterValue; // the value of the counter
};

Secondly we need to specify the public interface (i.e. methods) of the class. This applies to operators, functions and data.

  class Counter
{
protected:
int X_Pos;
int Y_Pos;
int CounterValue;
public:  // The following items are public
// Same name therefore a constructor
Counter (int X, int Y, int val = 0);
int operator += (int Val); // <Counter> += <int>
int operator ++ (void);   // <Counter>++
int operator = (int);    // <Counter> = <int>
// for <int> = <Counter>
friend int& operator = (Counter&);
};

Thirdly, we need to decide on the functions and data that are needed by the class for its internal usage.

  class Counter
{
protected:
int X_Pos;
int Y_Pos;
int CounterValue;
void Display(void);  // to display the counter public:
Counter (int X, int Y, int val =0);
int operator += (int Val);
int operator ++ (void);
int operator = (int&);
friend int operator = (Counter&);
};

All the member functions of the Counter class have been written 'out-of-line', the other alternative is that they could have been written 'in-line' and included in the class definition.

If the display function was to be written 'in-line' it would be within the class definition and look like this:

  void Display (void) 
{
constream console;
console << setxy(X_Pos, Y_Pos) << CounterValue;
}

Written 'out-of-line' the display function will look as follows:

  void Counter::Display()
{
constream console;
console << setxy(X_Pos, Y_Pos)
<< setw(5) << CounterValue;
}

The structure of the 'out-of-line' member function is as follows:

  <return-type>  <Class-name>::<member function name>
( <params>..)
{
<function statements);
}

Lets look at some of the other functions. Any member function that has the same name as the class is known as a constructor. If the name is preceded by a tilde (~) and is the same as the class name it is known as a destructor.

The constructor and destructor member functions are never called by the programmer, they are called by the compiler at the creation and destruction of the object (i.e. when it comes into scope and it leaves scope).

The Counter member function takes 2 or 3 parameters, yes C programmers (2||3 parameters). The third parameter, if not supplied is defaulted to the number specified in the class declaration.

  Counter::Counter (int X, int Y, int val) 
{
// copy the parameters into the class
X_Pos = X;
Y_Pos = Y;
CounterValue = val;
// and display it on the screen at the desired
// position
Display ();
}

With C++ classes, it is not only functions that can be used, operators can also be custom built to suit the class. The general structure of the operator is as follows:

  <return-type>  <Class-name>::operator <operator>   
(<params>..)
{
<function statements);
}

The first needed operator is the equal sign

  int Counter::operator = (int Val) 
{
CounterValue = Val;
Display();
return CounterValue;
}

This operator is used to assign an integer value to acounter. The += and ++ operators follow a very similar pattern.

This allows the programmer to use += to increase the value on the screen, e.g.

  Counter score(20,24,0);
  if (space_invader->hit())
    score+=space_invader->value();

  int Counter::operator ++ (void) {
    CounterValue++;
    Display() ;
    return CounterValue;
  }

The ++ operator allows a screen counter to be incremented easily, e.g.

  Counter num_recs(10,10,0);
  if (get_record()==0K)
  {
    process_record();
    num_recs++;
  }

The situation can also occur when you want to assign the value of the class to an integer. This is a situation in which the function produced cannot be a member function as it is not an action on the object of the type Counter, but an action on type int. For this to happen the function must be declared within the class as a friend of the class. This has the effect of allowing the function access to the data members of Counter.

This function looks a little strange to C programmers as it uses references to values, not pointers to values. A reference is like an automatically de-referenced pointer.

  int& operator = (Counter& K)
  {
    return K.CounterValue;
  }

The main program is very simple to follow and requires no annotation:

  void main (void)
  {
    Counter myscore(10,10), // declaration of score
    computer_score(30,10,3); // positions & values while
    ((myscore++)<1000) {
      compute r_score++;
    }
}





Your Privacy

By clicking "Accept Non-Essential Cookies" you agree ACCU can store non-essential cookies on your device and disclose information in accordance with our Privacy Policy and Cookie Policy.

Current Setting: Non-Essential Cookies REJECTED


By clicking "Include Third Party Content" you agree ACCU can forward your IP address to third-party sites (such as YouTube) to enhance the information presented on this site, and that third-party sites may store cookies on your device.

Current Setting: Third Party Content EXCLUDED



Settings can be changed at any time from the Cookie Policy page.