Introduction to Programming and C++

Contents Previous Topic Next Topic

Objects and object-oriented programming is a relatively new concept in computer science. An object-oriented language Smalltalk has been around for some time, and is almost as old as C, however, due to the relative infancy of compiler technology, it did not produce very fast code and was therefore mostly an academic curiosity.

Thus, C does not have objects, however, they have something a lot simpler: a struct, or structure. A struct is basically a class with nothing other than the class members:

  1. Everything is public,
  2. There are no member functions,
  3. There are no constructors or destructors, and
  4. Thus, any initialization or cleanup must be explicitly done by the programmer.

The keyword is struct instead of class, and unlike C++, the structure name does not immediately define a new type. Program 1 demonstrates a simple complex number class.

Program 1. A complex structure.

#include <stdio.h>

struct complex {
	double re;
	double im;
};

struct complex add( struct complex z, struct complex w ) {
	struct complex sum;

	sum.re = z.re + w.re;
	sum.im = z.im + w.im;

	return sum;
}

struct complex multiply( struct complex z, struct complex w ) {
	struct complex product;

	product.re = z.re*w.re - z.im*w.im;
	product.im = z.re*w.im + z.im*w.re;

	return product;
}

int main() {
	struct complex a = {3.5, -4.9};
	struct complex b = {2.7, -3.8};

	struct complex result = add( a, b );

	printf( "%lf + i%lf\n", result.re, result.im );

	a.re = 0.3;

	result = multiply( a, b );

	printf( "%lf * i%lf\n", result.re, result.im );

	return 0;
}

When you compare Program 1 to the equivalent C++ program shown in Program 2, it appears quite primitive.

Program 2. The equivalent Complex class in C++ of Program 1.

#include <iostream>

using namespace std;

class Complex {
    private:
        double re;
        double im;

    public:
        Complex( double r, double i ):re( r ), im( i ) {}

        void set_real( double r ) { re = r; }
        void set_imag( double i ) { im = i; }

        friend Complex operator + ( const Complex &, const Complex & );
        friend Complex operator * ( const Complex &, const Complex & );
        friend ostream & operator << ( ostream &, const Complex & );
};

Complex operator + ( const Complex & z, const Complex & w ) {
    return Complex( z.re + w.re, z.im + w.im );
}

Complex operator * ( const Complex & z, const Complex & w ) {
    return Complex(
        z.re*w.re - z.im*w.im, z.re*w.im + z.im*w.re
    );
}

// We could do this without friendship by calling z.real() andz. imag(), but almost always,
// printing will require some access to private member variables or private member functions

ostream & operator << ( ostream & out, const Complex & z ) {
    if ( z.im < 0.0 ) {
        return out << z.re << "-" << (-z.im) << "j";
    } else {
        return out << z.re << "+" << z.im << "j";
    }
}

int main() {
    Complex a(3.5, -4.9);
    Complex b(2.7, -3.8);

    cout << "The sum of " << a << " and " << b
         << " is " << a + b << endl;

    a.set_real( 0.3 );

    cout << "The product of " << a << " and " << b
         << " is " << a * b << endl;

    return 0;
}

Aside from the differences mentioned above, you can still use . and -> with structures as you would have with classes. If you call sizeof, for example, on the complex class shown in Program 1, it will return 16, the number of bytes in two doubles. Thus, you can create arrays of structures and manipulate them as if they were classes where all the class members are public.

Comment

Years ago, the problem was trying to teach students who were used to structures what the benefits of classes were. Here we are teaching structures to the students who know the benefits of classes, and as such, may become very frustrated very quickly.


Contents Previous Topic Top Next Topic