Classes, pointers, and references in C++

A struct in C++ is just like a struct in C, a data structure with 'fields'. For example, the struct

typedef  struct

{

  double real;

  double img;

} Complex;

enables one to declare a Complex variable with a statement like

Complex z,w;

so that later in the program the value of z can be assigned with statements like

z.real = 3.4;

z.img = -2.3;

A class in C++ is a very flexible data structure. The fields of the class are divided into public and private fields

This enables one to hide information (and protect it). Also a field can be a function! This enables one to have special input and output functions to handle the data that are stored in the class. See your text, chapter 10, for more details. A definition of a vector class is given below. Definitions of classes are usually stored in header files (.h files).

A pointer variable in C++ is just like a pointer variable in C. It holds an address which points to the location

where a value is stored. A reference variable in C++ is similar to a pointer, but is less cumbersome to use in many cases. For example, if you wanted a function to add two Complex numbers you could define it in several ways:

Complex cadd( Complex z,  Complex w)

{

  Complex t;

  t.real = z.real + w.real;

  t.img = z.img + w.img;

  return t;

}

In this procedure, the inputs z and w are passed by value, that is, if a call cadd(a,b) is made then copies of a and b are made and sent to the procedure for use. Often one would use a pointer variable in the inputs, so the code is

Complex cadd( const Complex *z,  const Complex *w)

{

  Complex t;

  t.real = z->real + w->real;

  t.img = z->img + w->img;

  return t;

}

This saves space when the data structures being passed are large and expensive to copy. Note: Then constant declaration is put in avoid inadvertantly changing the value of z or w in cadd.

Reference variables in C++ can be used in place of pointers when passing by reference. The code is cleaner:

Complex cadd( const Complex  & z,  const Complex & w)

{

  Complex t;

  t.real = z.real + w.real;

  t.img = z.img + w.img;

  return t;

}

Read in your book about pointers and references in chapter 5.

Using the library libmv.a to handle vectors and matrices.

The standard libraries for C++ have one and two dimensional arrays built in, but they are very primitive. What one would like to be able to do is have a vector class and a matrix class defined in C++ which make it simple and as transparent as possible to work with vectors and matrices. We will make use of a very nice definition of these classes devised by Roldan Pozo. For example, here is his definition of a vector class.

mvvd.h

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* */
/* */
/* MV++ Numerical Matrix/Vector C++ Library */
/* MV++ Version 1.5 */
/* */
/* R. Pozo */
/* National Institute of Standards and Technology */
/* */
/* NOTICE */
/* */
/* Permission to use, copy, modify, and distribute this software and */
/* its documentation for any purpose and without fee is hereby granted */
/* provided that this permission notice appear in all copies and */
/* supporting documentation. */
/* */
/* Neither the Institution (National Institute of Standards and Technology) */
/* nor the author makes any representations about the suitability of this */
/* software for any purpose. This software is provided ``as is''without */
/* expressed or implied warranty. */
/* */
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

//
// mv_vector_double.h Basic vector class (double precision)
//

#ifndef _MV_VECTOR_double_H
#define _MV_VECTOR_double_H



#include <stdlib.h>
#include <iostream.h> // for formatted printing of matrices


#ifdef MV_VECTOR_BOUNDS_CHECK
# include <assert.h>
#endif

#include "mvvind.h"

// this is really used as a sort of global constant. The reason
// for creating its own type is that so it can be overloaded to perform
// a deep or shallow assignement. (Any variable of type MV_Vector_::ref_type
// has only one possible value: one.)
// It is included as a seperate file to avoid multiple definitions.

#include "mvvrf.h"

class MV_Vector_double
{
protected:
double *p_;
unsigned int dim_;
int ref_; // 0 or 1; does this own its own memory space?
public:

/* Constructors/Destructors */

MV_Vector_double();
MV_Vector_double(unsigned int);
MV_Vector_double(unsigned int, const double&);


MV_Vector_double(double*, unsigned int);
MV_Vector_double(const double*, unsigned int);
MV_Vector_double(const MV_Vector_double &);

// reference of an exisiting data structure
//
// note that ref() is initalized with i rather than 1.
// this is so compilers will not generate a warning that i was
// not used in the construction. (MV_Vector::ref_type is an enum that
// can *only* have the value of 1.
//
MV_Vector_double(double* d, unsigned int N, MV_Vector_::ref_type i) :
p_(d), dim_(N), ref_(i) {}

MV_Vector_double(const MV_Vector_double &V, MV_Vector_::ref_type i) :
p_(V.p_), dim_(V.dim_), ref_(i) {}

~MV_Vector_double();

/* Indices and access operations */

double& operator()(unsigned int i)
{
# ifdef MV_VECTOR_BOUNDS_CHECK
assert(i < dim_);
# endif
return p_[i];
}
const double& operator()(unsigned int i) const
{
# ifdef MV_VECTOR_BOUNDS_CHECK
assert(i < dim_);
# endif
return p_[i];
}

double& operator[](unsigned int i)
{
# ifdef MV_VECTOR_BOUNDS_CHECK
assert(i < dim_);
# endif
return p_[i];
}
const double& operator[](unsigned int i) const
{
# ifdef MV_VECTOR_BOUNDS_CHECK
assert(i < dim_);
# endif
return p_[i];
}
MV_Vector_double operator()(const MV_VecIndex &I) ;
MV_Vector_double operator()(void);
const MV_Vector_double operator()(void) const;
const MV_Vector_double operator()(const MV_VecIndex &I) const;

inline unsigned int size() const { return dim_;}
inline unsigned int dim() const { return dim_;}
inline int ref() const { return ref_;}
inline int null() const {return dim_== 0;}
//
// Create a new *uninitalized* vector of size N
MV_Vector_double & newsize(unsigned int );

/*::::::::::::::*/
/* Assignment */
/*::::::::::::::*/

MV_Vector_double & operator=(const MV_Vector_double&);
MV_Vector_double & operator=(const double&);

friend ostream& operator<<(ostream &s, const MV_Vector_double &A);
};
#endif

He went ahead to make a library he called libmv.a (and the source files to build it) of basic procedures to work with these classes. The zipfile mvmaple.zip contains the current version of my attempts to use the library to implement the export of maple procedures to C++. A goal here might be to expand the library to include a number of procedures with the same name and syntax as in Maple. This would make it easier to export procedures.