Engineering Problem Solving with C++, Etter/Ingber

57
Engineering Problem Solving with C++, Etter/Ingber Chapter 10 Additional Topics in Programming with Classes Engineering Problem Solving with C++, Second Edition. J. Ingber 1

description

Engineering Problem Solving with C++, Etter/Ingber. Chapter 10 Additional Topics in Programming with Classes. Programming with Classes. Introduction to Generic Programming Recursion Class Templates Inheritance virtual Methods. function templates overloading operators friend functions. - PowerPoint PPT Presentation

Transcript of Engineering Problem Solving with C++, Etter/Ingber

Page 1: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Etter/Ingber

Chapter 10

Additional Topics in Programming with Classes

Engineering Problem Solving with C++, Second Edition. J. Ingber

1

Page 2: Engineering Problem Solving with C++, Etter/Ingber

Programming with Classes

Introduction to Generic Programming Recursion Class Templates Inheritance virtual Methods

Engineering Problem Solving with C++, Second Edition. J. Ingber

2

Page 3: Engineering Problem Solving with C++, Etter/Ingber

INTRODUCTION TO GENERIC PROGRAMMING

function templates

overloading operators

friend functions

Engineering Problem Solving with C++, Second Edition. J. Ingber

3

Page 4: Engineering Problem Solving with C++, Etter/Ingber

Generic Programming

Generic programming supports the implementation of a type independent algorithm.

Type independent algorithms can be defined in C++ using the keyword template, and at least one parameter.

The compiler generates a unique instance of the template for each specified type.

Engineering Problem Solving with C++, Second Edition. J. Ingber

4

Page 5: Engineering Problem Solving with C++, Etter/Ingber

Function Templates A function template is a parameterized function definition.

Syntax:template<typename identifier [,typename identifier,…] >

return-type function name(parameter list)

{ …}

Example:template<typename Dtype>

void swapTwo(Dtype& a, Dtype& b)

{

Dtype temp = a;

a = b;

b = temp;

}

Engineering Problem Solving with C++, Second Edition. J. Ingber

5

Page 6: Engineering Problem Solving with C++, Etter/Ingber

Instantiating TemplatesExample:template<typename Dtype& a, Dtype& b>

void swapTwo(Dtype& a, Dtype& b); //prototype

int main()

{

double x(1.0), y(5.7);

char ch1('n'), ch2('o');

swapTwo(x,y);

swapTwo(ch1, ch2);

cout << x << ',' << y << endl

<< ch1 << ch2 << endl;

...

Engineering Problem Solving with C++, Second Edition. J. Ingber

6

Output:5.7, 1.0on

Page 7: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

7

Overloading Operators

Allows a programmer defined data type to be used in the same way that a predefined data type is used.

Definitions for overloaded operators are included in the class definition.– keyword operator is used followed by the operator.– the operator must be one of the predefined C++

operators.– Only predefined operators may be overloaded.

All predefined operators except( . :: .* ?: sizeof) may be overloaded.

Page 8: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

8

Complex Number Class

A complex number is a number that has two components; the real component and the imaginary component.

a + biArithmetic is defined as follows:

(a + bi) + (c + di) = (a + c) + (b + d)i

(a + bi) - (c + di) = (a - c) + (b - d)i

(a + bi) * (c + di) = (ac - bd) + (ad + bc)i

(a + bi) / (c + di) = (ac + bd) / (c**2+d**2) +

[ (bc -ad) /(c**2+d**2)]i

Page 9: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

9

Class Declarationclass complex{ public:

complex();complex(double,double);void print(ostream&);void input(istream&);complex operator+(complex) const;complex operator-(complex) const;complex operator*(complex) const;complex operator/(complex) const;

private:double real, imag;

};

Page 10: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

10

Implementation - constructors

complex::complex(){ //default constructor real=imag=0;}

complex :: complex(double r, double im){ real = r;

imag = im;}

Page 11: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

11

Implementation – Overloaded Operators

complex complex::operator+(complex c) const{ complex temp; temp.real = real + c.real; temp.imag = imag + c.imag; return temp;}

Page 12: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

12

Implementation - Continued

complex complex::operator/(complex c) const{ complex temp; temp.real = (real*c.real + imag*c.imag)/

( pow(c.real,2) + pow(imag,2) ); temp.imag = (imag*c.real - real*c.imag)/

( pow(c.real,2) + pow(imag,2) ); return temp;}

Page 13: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

13

Practice! – Implement the * operator(a + bi) * (c + di) = (ac - bd) + (ad + bc)i

complex complex::operator*(complex c) const{ complex temp; temp.real = real*c.real – imag*c.imag; temp.imag = real*c.imag + imag*c.real; return temp;}

Page 14: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

14

Test Program complex c1, c2, c3; //declare three complex variablesc1.input(cin);c2.input(cin);

//test addition c3 = c1 + c2; // using overloaded operator + cout << endl << "c1 + c2 is "; c3.print(cout);

//test divisionc3 = c1 / c2; // using overloaded operator /cout << endl << "c1 / c2 is ";c3.print(cout);cout << endl;

Page 15: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

15

Sample Output

Using the following input:

4.4 1.53.5 -2.5

The expected output from our test program will be:

c1 + c2 is 7.9 + -1ic1 / c2 is 0.62973 + 0.878378i

Page 16: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

16

Variations

Overloading Operators as:– member functions – friend functions – top level functions

Page 17: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

17

Member Functions

binary operators (ie +,-, * )– member function requires one argument– the left hand operand is the object invoking the operator

unary operator– member function requires no arguments– assumed to be prefix version of operators ++ and –– postfix versions of operators ++ and – are not covered

in this text Disadvantages

– first argument must be an object of the class

Page 18: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

18

Example – class complex

In complex.h– complex operator +(complex c);

operator + implemented in complex.cpp In a client program

complex a, b, c;c = a + b; //a is calling object, b is argumentc = a + 54.3; //OK, constructor is called to

// convert 54.3 to complex object

c = 54.3 + a // is not allowed

Page 19: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

19

Friend Functions binary operators

– friend function requires two arguments unary operator

– friend function requires one argument Disadvantage

– A friend function is NOT a member function – Friend functions violate a strict interpretation of

object oriented principals (implementation is hidden)– Recommended for operator overloading only

Page 20: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

20

Example: In class definition:

friend complex operator +(complex c1, complex c2); In class implementation:

complex operator +(complex c1, complex c2){ complex temp; temp.real = c1.real + c2.real; temp.imag = c1.imag + c2.imag; return temp;}

In client program:complex cA, cB, cC;cC = cA+cB;cC = 54.3 + cB; //this is ok, when + is a friend function

Page 21: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

21

Class Declarationclass complex{ public: complex(); complex(double,double); friend ostream& operator <<(ostream&, complex); friend istream& operator >>(istream&, complex&); complex operator+(complex) const; complex operator-(complex) const; complex operator*(complex) const; complex operator/(complex) const; private: double real, imag;};

Page 22: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

22

Implementation

ostream& operator <<(ostream& os, complex r){ os << r.real << “ + “ << r.imag << ‘i’;

return os;}

istream& operator >> (istream& is, complex& r){ is >> r.real >> r.imag;

return is;}

Page 23: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

23

Error Checking on input operatorIf your input fails because of incorrect format, your function should mark the state of the istream as bad

is.clear(ios::badbit | is.rdstate() )

clear resets entire error state to zero

clear(ios::badbit) clears all and sets badbit

is.rdstate() returns the previous state of all bits

Statement sets the bit vector to the OR of badbit with previous state

Page 24: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

24

Top Level Functions

binary operators– top level function requires two arguments

unary operator– top level function requires one argument

Disadvantage:– Top level functions do not have access to

private data members. Function must use accessor functions.

Page 25: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

25

Example of top level function

Function prototype in client program.complex operator +(complex c1, complex c2);

Implemention in client program.complex operator +(complex c1, complex c2){ return complex(c1.get_real() + c2.get_real(),

c1.get_imag() + c2.get_imag());}

Use in client program.complex cA, cB, cC;cC = cA + cB;cC = 54.3 + cA; //this is ok, when + is a top level

//function

Page 26: Engineering Problem Solving with C++, Etter/Ingber

RECURSION

factorial function

binary trees

Engineering Problem Solving with C++, Second Edition. J. Ingber

26

Page 27: Engineering Problem Solving with C++, Etter/Ingber

Recursion Recursion is a powerful tool for solving certain

classes of problems where:– the problem solution can be expressed in terms of the

solution to a similar, yet smaller problem.

Redefinition of the problem continues in an iterative nature until:– a unique solution to a small version of the problem is

found.

This unique solution is then used, in a reverse iterative nature until:– the solution to the original problem is returned.

Engineering Problem Solving with C++, Second Edition. J. Ingber

27

Page 28: Engineering Problem Solving with C++, Etter/Ingber

Recursion Programming languages that support recursion

allow functions to call themselves. Each time a function calls itself, the function is

making a recursive function call. Each time a function calls itself recursively,

information is pushed onto the runtime stack. Each time a recursive function calls returns,

information is popped off the stack. The return value, along with the information on the stack, is used to solve the next iteration of the problem

Engineering Problem Solving with C++, Second Edition. J. Ingber

28

Page 29: Engineering Problem Solving with C++, Etter/Ingber

Recursive Functions

A recursive function requires two blocks:– a block that defines a terminating condition, or

return point, where a unique solution to a smaller version of the problem is returned.

– a recursive block that reduces the problem solution to a similar but smaller version of the problem.

Engineering Problem Solving with C++, Second Edition. J. Ingber

29

Page 30: Engineering Problem Solving with C++, Etter/Ingber

Example: Recursive Definition of Factorial Function

Engineering Problem Solving with C++, Second Edition. J. Ingber

30

}1:)1(*,0:1{!)( nnfnnnnf

f(0) = 1 Unique solution.f(n) = n*f(n-1) Recursive definition.Thus, f(n) can be determined for all integer values of n>=0;

Page 31: Engineering Problem Solving with C++, Etter/Ingber

Recursive Factorial Function long factorialR(int n)

{

/*Termination condition */

if(n==0)

{

return 1; //unique solution

}

/*Recursive block – reduce problem */

return n*factorialR(n-1);

}

Engineering Problem Solving with C++, Second Edition. J. Ingber

31

Page 32: Engineering Problem Solving with C++, Etter/Ingber

32

• A binary tree maintains two links between nodes.

• The links are referred to as the left child and the right child.

• The first node is called the root.

• Each child(left and right) may serve as the root to a subtree.

• A node without children is referred to as a leaf node.

Binary Tree Abstraction

Page 33: Engineering Problem Solving with C++, Etter/Ingber

33

Diagram

+

2

8

4

*

pointer to root

leaf node leaf node

Page 34: Engineering Problem Solving with C++, Etter/Ingber

34

• A BinaryTree class with one attribute:

a pointer (node*) to the root of a binary tree.

Implementation

Page 35: Engineering Problem Solving with C++, Etter/Ingber

35

Methods:

insert()

delete()

print()

inOrder(), preOrder(), postOrder()

Implementation of insert:

Insert into empty BinaryTree establishes the root.

Each subsequent node is inserted in order:

values less than root are placed in the root’s left subtree

values greater than root are placed in the root’s right subtree

BinaryTree class

Page 36: Engineering Problem Solving with C++, Etter/Ingber

36

display node

visit left child

visit right child

*+248

preOrder Traverse

Page 37: Engineering Problem Solving with C++, Etter/Ingber

37

visit left child

visit right child

display node

24+8*

postOrder Traverse

Page 38: Engineering Problem Solving with C++, Etter/Ingber

38

Visit left child

Display node

Visit right child

2+4*8

inOrder Traverse

Page 39: Engineering Problem Solving with C++, Etter/Ingber

BinaryTree Class Recursive Methods:

– print(), insert(), clear()

Recursive methods are overloaded. public version is non-recursive. public version is called once. public version calls private recursive

version. Recursive version calls itself.

Page 40: Engineering Problem Solving with C++, Etter/Ingber

CLASS TEMPLATESbinary tree

Engineering Problem Solving with C++, Second Edition. J. Ingber

40

Page 41: Engineering Problem Solving with C++, Etter/Ingber

class Templates

A binary tree is an ordered collection of nodes. Each node has a data value, a right child and a

left child. The data type of the right and left child is node*.

The data type of the node value is parameterized to form a class template.

The binary tree template also parameterizes the node type..

Engineering Problem Solving with C++, Second Edition. J. Ingber

41

Page 42: Engineering Problem Solving with C++, Etter/Ingber

42

#include "node.h"

template<typename T>class BinaryTree {public:

BinaryTree():root(0){} //inline

bool empty(){return root==0;} //inline

void clear(){ if(root) {clear(root); root=0;} } //inline, non recursive

void insert(const T& );

//…

private:

void clear(node<T>*); //recursive node<T>* root; //node is a class template};

BinaryTree Declaration

Page 43: Engineering Problem Solving with C++, Etter/Ingber

43

//cleartemplate<typename T> void BinaryTree<T>::clear(node<T> *pt) //method called from private clear() { if(pt){ clear(pt->getLeft()); clear(pt->getRight()); delete pt;} }

//inserttemplate<typename T> void BinaryTree<T>::insert(const T& value) { if(!root) root = new node<T> (value); //must qualify else root->insertValue(value); //member of node }

Implementation of BinaryTree class

Page 44: Engineering Problem Solving with C++, Etter/Ingber

44

template<typename valType> void node<valType>::insertValue(const valType& val){ if(val < data){ if(!left) left=new node(val); //don’t need to quality else left->insertValue(val); } else { if(!right) right = new node(val); else right->insertValue(val); } }

insertValue: member of node class

Page 45: Engineering Problem Solving with C++, Etter/Ingber

45

int main(){ BinaryTree<int> tree; if(tree.empty()) cout << "empty" << endl; tree.insert(10); if(tree.empty()) cout << "empty" << endl; else cout << "not empty\n"; tree.clear(); if(tree.empty()) cout << "empty" << endl; else cout << "not empty\n"; return 0;}

output:

emptynot emptyempty

Sample Run

Page 46: Engineering Problem Solving with C++, Etter/Ingber

46

Suggestions for Writing templates

• Get a non-template version working first.

• Establish a good set of test cases.

• Measure performance and tune.

• Review implementation:• Which types should be parameterized?

• Convert non-parameterized version into template.

• Test template against established test cases.

Page 47: Engineering Problem Solving with C++, Etter/Ingber

INHERITANCE

Engineering Problem Solving with C++, Second Edition. J. Ingber

47

Page 48: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

48

Inheritance

Inheritance is a means by which one class acquires the properties--both attributes and methods--of another class.

When this occurs, the class being inherited from is called the base class.

The class that inherits is called the derived class.

Page 49: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

49

C++ and Public Inheritance

The private members of a base class are only accessible to the base class methods.

The public members of the base class, are accessible to the derived class and to clients of the derived class.

The protected members of the base class, are accessible to members of the derived class, but are not accessible to clients of the base class or clients of the derived class.

Page 50: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

50

UML Inheritance Diagram:

•A Rectangle has a Point.•Square is a Rectangle.

Page 51: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

51

Example – Base Class Definitionclass Rectangle{

private:double width, height;Point origin;

public:Rectangle();Rectangle(double w, double h, double x, double y); //Accessors//Mutators

};

Page 52: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

52

Example: Derived Class

class Square : public Rectangle {

public:Square();Square(const Point&, double s);double getSide() const;void setSide(double);

};

Page 53: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

53

Constructors and Inheritance

When an object is created, its constructor is called to build and initialize the attributes.

With inheritance, the invocation of constructors starts with the most base class at the root of the class hierarchy and moves down the path to the derived classes constructor.

If a class is to use the parameterized constructor of a base class, it must explicitly invoke it.

Page 54: Engineering Problem Solving with C++, Etter/Ingber

Engineering Problem Solving with C++, Second Edition. J. Ingber

54

Implementation of Constructor

Rectangle::Rectangle(double w, double h, double x, double y) : origin(x,y){}

Square::Square(const Point&p, double side) : Rectangle(side,side)

{}

Page 55: Engineering Problem Solving with C++, Etter/Ingber

VIRTUAL METHODS

Engineering Problem Solving with C++, Second Edition. J. Ingber

55

Page 56: Engineering Problem Solving with C++, Etter/Ingber

Methods All methods are, by default, non-virtual methods.

Binding of method call is determined by static type of calling object.

Example:Rectangle r1;

Square s1;

r1 = s1;

r1.print(cout);//Calls print() defined in

//Rectangle

Engineering Problem Solving with C++, Second Edition. J. Ingber

56

Page 57: Engineering Problem Solving with C++, Etter/Ingber

virtual Methods

If a method is defined to be virtual, and pointers or references to objects are used, then dynamic binding is supported.

Example:Rectangle *rPtr;

Point p2;

Square s1 = s1(p2,5);

rPtr = &s1;

rPtr->print(cout);//Calls print() defined in

//Square

Engineering Problem Solving with C++, Second Edition. J. Ingber

57