C++ Workshop

Designing and Implementing Classes

References
C++ Programming Language, Bjarne Stroustrup, Addison-Wesley C++ and Object-Oriented Numeric Computing for Scientists and Engineers, Daoqi Yang, Springer Scientific and Engineering C++, John J. Barton and Lee R. Nackman, Addison-Wesley

Rational Class Mechanics
Goal: Design and test a class, Rational, for manipulating rational numbers Components:
±

rational.h ² header file with definition of the class including member data and functions rational.cpp ² implementation of member functions testrat.cpp ² a small program to test the class definition

±

±

Access
Keywords: private (default), public, protected, friend private ² members can accessed only by other member functions or operators of the class public ² members can be used directly by client programs protected ² members can be used only by other member functions or operators of the class or derived classes

} .Client Program Example Revisited #include <iostream> #include <string> #include ³rational. cout << r << ³+´ << s << ³=³ << Sum << endl. s(2/3). return(0). Rational t(r). Rational Sum = r + s.h´ using namespace std. Rational Product = r * s. int main() { Rational r(3/4).

r.4). //illegal ± data is private int a = GetNumerator(r) //illegal ± function is protected r.SetNumerator(b).Statements not permissible due to access restrictions Rational r(3. //illegal ± function is protected .ImaginaryValue = 6.

Use in external program or function: ± ± Rational b(3. //data not initialized Rational (int numer. ± ± use in external program or function: Rational b. //denominator defaults to 1 . int denom=1).Constructors Rational ().4). //data is ¾ Rational c(4).

e.const qualifier Objects may also be declared as constants.g. const objects require const member functions const member functions can be used with both const and non-const objects Example: ± ± Rational Add(const Rational &r) const.2). Object is passed by reference (&r). ± const Rational OneHalf(1. const qualifier prevents modification const member function will not modify any of object's data members ± .

int GetDenominator() const.Inspectors Note: protected not accessible to main or external functions Used to retrieve member data int GetNumerator() const. const qualifier permits use with const objects .

void SetDenominator(int denom). .Mutators Modify member data Protected access void SetNumerator(int numer).

Arithmetic Functions Rational Add(const Rational &r) const. The result is another Rational object which is assigned to t . Rational t =r. Public member functions ² accessible in main and other functions Example usage: ± ± ± ± Rational r(3. Explanation: r is a rational object invoking its public member function Add with the rational object s as an argument.Add(s).4). Rational s(2.5).

± inserts a representation of the object into the output stream referenced by &sout extracts a representation of the object from the input stream referenced by &sin void Extract(istream &sin) const.Stream Facilitators public access void Insert(ostream &sout) const. ± .

cout << ³Enter rational number (a/b): ³. Rational t = r.Extract(cin). cout << ³Enter rational number (a/b): ³.Add(s). s. t. cout << endl.Stream use examples Rational r: Rational s. These member functions still have to be //implemented . //note: illustrations of use are based only on the //definitions.Insert(cout).Extract(cin). r.

reserved word operator indicates operator overloading returns a Rational object .Overloaded Operators Rational operator+(const Rational &r. const Rational &s).

Implementation use a . } .cpp file Syntax for member function implementation header: <return-type> <classname>::<functionname>(<parameters>) Example: ± ± ± void Rational::SetNumerator(int numer) { NumeratorValue=numer.cc or .

int denom) { SetNumerator(numer). } //numer. SetDenominator(1). denom constructor Rational::Rational(int numer. SetDenominator(denom).Constructors Implementation //default constructor Rational::Rational() { SetNumerator(0). } //Notice: both constructors are invoking protected member functions SetNumerator and SetDenominator .

} //get denominator int Rational::GetDenominator() const { return DenominatorValue. } .Inspector Implementations //get numerator int Rational::GetNumerator() const { return NumeratorValue.

} } . } //set denominator void Rational::SetDenominator(int denom) { if (denom != 0) { DenominatorValue = denom.Mutator Implementation //set numerator void Rational::SetNumerator(int numer) { NumeratorValue = numer. DenominatorValue = 1. } else { cerr << ³Illegal denominator: ³ << denom << ³using 1´ << endl.

return Rational(a*d + b*c. b*d). int b = GetDenominator().GetDenominator(). int c = r. } //Note that the return invokes the constructor . int d = r.GetNumerator().Arithmetic Function Implementation One example will suffice: Rational Rational::Add(const Rational &r ) const { int a = GetNumerator().

return. } //Extracting a Rational void Rational::Extract(istream &sin) { //input a/b int numer.Stream Insertion and Extraction . char slash. sin >> numer >> slash >> denom. SetNumerator(numerb). SetDenominator(denom).Implement //Inserting a Rational void Rational::Insert(ostream &sout) const { //output as a/b sout << GetNumerator() << '/' << GetDenominator(). } . int denom.

Operator implementation Again. const Rational &s) { return r.Add(s). } . one example: Rational operator+(const Rational &r.

e. //s is copy constructed from r C++ also automatically makes assignment available. no return value . C++ automatically makes destructor member function available.g. Rational t = r. ~Rational() -Restrictions: no parameters. Rational r(1.g.2). Rational s(r).Automatic member functions C++ automatically makes copy constructor available: e.

return *this. int b = r. } .getDenominator(). SetDenominator(a). } //Rational: destructor Rational::~Rational() {} //Rational: assignment operator Rational& Rational::operator=(const Rational &r) { int a = r. int b = r.getNumerator(). SetDenominator(a).GetDenominator().Explicit Implementation //Rational copy constructor Rational::Rational(const Rational &r) { int a = r. SetNumerator(b). SetNumerator(b).GetNumerator().

What is *this ? this is a keyword for the address of the object whose member function is being invoked * is the dereferencing operator *this is the value of the object at that address .

e. Create rational. Link the driver to the class module: g++ -o testrat testrat.o . Compile: g++ -c rational.g.Putting it all together 1. testrat.cpp file with implementations for member functions 3. Create rational. Create a simple driver program using the class.cpp 5. Compile the driver g++ -c testrat.o rational.cpp 4.h file with class definitions 2. call example program.cpp 5.

Other possible member functions for Rational class operator += (and other op=) operator == ++. -- .

walk through construction of user-defined Complex Class .MyComplex Class Using example of Rational Class.

Point Class 2 dimensional point attributes: x. parameters 2: another point draw ² for now.y coordinates. just print out ?? Other functions ± ± .y methods: ± ± Constructor (s) move ² parameters1 : x.

Integral Class ref: Yang evaluate definite integrals attributes: ± ± lower and upper bounds pointer to a function .

double b. //defining a function ptr class integral { double lower. double upbd() const {return upper. double trapezoidal(int) const. pfn f) { lower = a. //integrand function public: integral(double a. } . } double lowbd() const {return lower. double). integrand = f.Integral Class typedef double (*pfn)(double). double upper.}. . pfn integrand. friend double simpson(integral. upper = b.} void changebd(double. int).

sin).changebd(3. cout << result << endl. result = di.trapezoidal(100). 200). } . //change bounds di.7).5. cout << result << endl. result = simpson(di. cout << result << endl.Integral Class Use Example int main() { integral di(0.trapezoidal(100). double result = di.

Class MyVector Class MyVector: a vector Data: plain array Functions: subscripting. . change length. inner product with another vector.. This example is for illustration only.. assignment to another vector. A vector class is defined in the Standard Template Library .

Redimension a vector to length n: v.size(). Create a vector with zero length: MyVector v. Create a vector as a copy of another vector w: MyVector v(w). Extract the length of the vector: const int n = v. .redim(n).functionality Create vectors of a specified length: MyVector v(n).MyVector .

Set two vectors equal to each other: w = v.v). or alternatively a = inner(w.More functionality Extract an entry: double e = v(i). Assign a number to an entry: v(j) = e.inner(v). . Take the inner product of two vectors: double a = w.

the length of the vector.More functionality Write a vector to the screen: v.print(«). as well as a set of member functions for operating on the vector data Users can only operate on the vector data using the member Functions . Arithmetic operations with vectors« It is assumed that the example syntax would be defined in the MyVector class. MyVector consists of the data in the vector.

// MyVector v. / operators: MyVector operator* (double a. // clean up dynamic memory bool redim (int n). ~MyVector (). // free memory public: MyVector (). // v.inner(w). // MyVector v(w). MyVector& operator= (const MyVector& w).MyVector class possible definition class MyVector { private: double* A. // vector entries (C-array) int length. // v(i) = a. // v. // u = a*v. int size () const { return length. MyVector (int n). MyVector operator* (const MyVector& v. // a = v(i).// v = w. // u = v*a.size(). MyVector operator+ (const MyVector& a. MyVector (const MyVector& w). length=n void deallocate(). void print (ostream& o) const. // MyVector v(n). // a = v. double a). double inner (const MyVector& w) const.print(cout). double operator() (int i) const. void allocate (int n). const MyVector& v). double& operator() (int i). . // allocate memory. // u = a+b. const MyVector& b).redim(m). } // n = v.

Constructors . length = 0. } . // declare a vector of length 0 // this actually means calling the function MyVector::MyVector () { A = NULL.I MyVector v.

// create n doubles in memory } . A = new double[n]. // declare a vector of length n // means calling the function MyVector::MyVector (int n) { allocate(n). } void MyVector::allocate (int n) { length = n.Constructors II MyVector v(n).

} // free dynamic memory: void MyVector::deallocate () { delete [] A. The destructor specifies how to destroy the object: MyVector::~MyVector () { deallocate(). } . but must also be destroyed when it is no longer in use.Destructor A MyVector object is created (dynamically) at run time.

allows nested // assignments: u = v = u_vec = v_vec.Assignment Operator Set a vector equal to another vector: // v and w are MyVector objects v = w. . // make v as long as w int i. i < length. i++) { // (C++ arrays start at 0) A[i] = w.size()). } // return of *this.e. a MyVector&. means calling: MyVector& MyVector::operator= (const MyVector& w) // for setting v = w. return *this. { redim (w. for (i = 0. i.A[i].

return true. } //end if allocate(n).Redimensioning Length Change the length of an already allocated MyVector object: v. // no need to allocate anything else { if (A != NULL) { / "this" object has already allocated memory deallocate().redim(n). // the length was changed } //end else } . // make a v of length n Implementation: bool MyVector::redim (int n) { if (length == n) return false.

size()). // call operator= } this is a pointer to the current (³this´) object. // take a copy of w MyVector::MyVector (const MyVector& w) { allocate (w.Copy Constructor Create a new vector as a copy of an existing one: MyVector v(w). *this is the object itself . // "this" object gets w¶s length *this = w.

Subscripting // a and v are MyVector objects. } // returns a reference (µµpointer¶¶) directly to A[i-1] // such that the calling code can change A[i-1] . // base index is 1 (not 0 as in C/C++) } Inline functions: function body is copied to calling code. there is no guarantee that the compiler really inlines the function Why return a double reference? double& MyVector::operator() (int i) { return A[i-1]. no overhead of function call! Note: inline is just a hint to the compiler. want to set a(j) = v(i+1). // the meaning of a(j) is defined by inline double& MyVector::operator() (int i) { return A[i-1].