Vous êtes sur la page 1sur 43

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.h using namespace std; int main() { Rational r(3/4), s(2/3); Rational t(r); Rational Sum = r + s; Rational Product = r * s; cout << r << + << s << = << Sum << endl; return(0); }

Statements not permissible due to access restrictions


Rational r(3,4); r.ImaginaryValue = 6; //illegal data is private int a = GetNumerator(r) //illegal function is protected r.SetNumerator(b); //illegal function is protected

Constructors
Rational ();

use in external program or function: Rational b; //data not initialized

Rational (int numer, int denom=1); Use in external program or function:


Rational b(3,4); //data is Rational c(4); //denominator defaults to 1

const qualifier
Objects may also be declared as constants, e.g.

const Rational OneHalf(1,2);

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; Object is passed by reference (&r), const qualifier prevents modification const member function will not modify any of object's data members

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

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

Arithmetic Functions
Rational Add(const Rational &r) const; Public member functions accessible in main and other functions Example usage:

Rational r(3,4); Rational s(2,5); Rational t =r.Add(s); Explanation: r is a rational object invoking its public member function Add with the rational object s as an argument. The result is another Rational object which is assigned to t

Stream Facilitators
public access void Insert(ostream &sout) const;

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 use examples


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

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

Implementation
use a .cc or .cpp file Syntax for member function implementation header:
<return-type> <classname>::<functionname>(<parameters>)

Example:

void Rational::SetNumerator(int numer) { NumeratorValue=numer; }

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

Inspector Implementations
//get numerator int Rational::GetNumerator() const { return NumeratorValue; }

//get denominator int Rational::GetDenominator() const { return DenominatorValue; }

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

Arithmetic Function Implementation


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

Stream Insertion and Extraction - Implement


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

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

Automatic member functions


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

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

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

Putting it all together


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

Other possible member functions for Rational class


operator += (and other op=) operator == ++, --

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

Point Class
2 dimensional point attributes: x,y methods:

Constructor (s) move parameters1 : x,y coordinates, parameters 2: another point draw for now, just print out ?? Other functions

Integral Class
ref: Yang evaluate definite integrals attributes:

lower and upper bounds pointer to a function

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

Integral Class Use Example


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

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

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

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

More functionality
Write a vector to the screen: v.print(); 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, the length of the vector, 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

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

Constructors - I
MyVector v; // declare a vector of length 0 // this actually means calling the function

MyVector::MyVector () { A = NULL; length = 0; }

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

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

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

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

Copy Constructor
Create a new vector as a copy of an existing one: MyVector v(w); // take a copy of w MyVector::MyVector (const MyVector& w) { allocate (w.size()); // "this" object gets ws length *this = w; // call operator= }

this is a pointer to the current (this) object, *this is the object itself

Subscripting
// a and v are MyVector objects; 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]; // base index is 1 (not 0 as in C/C++) } Inline functions: function body is copied to calling code, no overhead of function call! Note: inline is just a hint to the compiler; 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]; } // returns a reference (pointer) directly to A[i-1] // such that the calling code can change A[i-1]

Vous aimerez peut-être aussi