程序代写代做代考 c++ compiler chain slides.ConvMSc

slides.ConvMSc

C++ the Object Based Paradigm, page: 1

Outline of the Course:

 C++, imperative programming ☺

 OO analysis, UML the object model ☺

 C++ the object-based paradigm

 C++, the object-oriented paradigm

 Abstract data types

 Templates

 Miscellaneous topics (exceptions etc.)

C++ the Object Based Paradigm, page: 2

The Language C++:

C++ = C

+ strong typing

+ classes

+ inheritance

+ overloading

+ information hiding

+ exceptions

+ templates

Bjarne Stroustrup Walter Savitch,

The C++ Programming Language Problem Solving with C++,

Addison Wesley 2000 Addison Wesley 2009.

Paul and Gail Anderson Deitel & Deitel

Navigating C++ C++ – How to program

Prentice Hall 1998 Prentice Hall, 2007

C++ the Object Based Paradigm, page: 3

Aims of this part of the course

 programming in the large using OO features

 understand the OO features in C++

 how to learn a programming language

How to work:

 read notes, think

 try out and modify examples from notes

 do tutorials and labs

C++ the Object Based Paradigm, page: 4

C++ the Object-based Paradigm

with many thanks to Jayshan Raghunandan

Object: An object has state, exhibits some well-defined behaviour,

and has a unique identity.

Class: A class describes a set of objects that share a common structure,

and a common behaviour.

A single object is an instance of a class.

C++ the Object Based Paradigm, page: 5

Classes in C++

“A class is a user-defined type. A class declaration specifies the

representation of objects of the class and the set of operations that

can be applied to such objects.”

A class comprises:

 data members: (or fields) each object of the class has its
own copy of the data members (local state)

 member functions: applicable to objects of the class

Data members describe the state of the objects. They have a type,

and are declared as:
type dataMemberId

C++ the Object Based Paradigm, page: 6

Member functions denote a service that objects offer to their clients.

The interface to such a service is specified by its return type and

formal parameter (s):
returnType memberFunctId( formalParams )

In particular, a function with void return type usually indicates a

function which modifies the state of the receiver.

A C++ program is organised in*

 header files,

 implementation files,

 main program file.

* Important for labs, but not important for exams/coursework.

C++ the Object Based Paradigm, page: 7

An example: the class Date

Date

day: int

month: int

year: int

next()

nextDate():Date

equal(Date):bool

print()

In this case we have three files: Date.h, Date.cpp, main.cpp.

//in file Date.h

class Date{ public:

int year, month, day;

void next();

bool equal(Date);

void print();

};

C++ the Object Based Paradigm, page: 8

//in file Date.cpp

#include

#include “Date.h”

void Date::next(){

day++ ;

if (this->day==32)

{ day = 1; month++;};

if ( (*this).month == 13 )

{ month=1; year++;}; }

bool Date::equal(Date aDate) {

return ((day==aDate.day)

&& (month==aDate.month))

&& (year==aDate.year); }

void Date::print( ) {

std::cout << day << " / " << month << " / " << year << endl; } C++ the Object Based Paradigm, page: 9 // in file mainDate.cpp #include

#include “Date.h”

int main(){

Date today, aDay;

today.day=30; today.month=10; today.year =

2007;

today.print();

// OUT: 30 / 10/ 2007

aDay.day=15; aDay.month= 5; aDay.year = 1984;

aDay.print();

// OUT: 15 / 5/ 1984

aDay = today;

/* if ( aDay==today )

std::cout << "same dates\n";*/ // compiler error message: // class Date does not define operator == C++ the Object Based Paradigm, page: 10 if ( aDay.equal( today )) std::cout << "today and tomorrow are equal \n"; // OUT: today and tomorrow are equal aDay.next();aDay.next(); aDay.print(); // OUT: 1 / 11/ 2007 today.print(); // OUT: 30 / 10/ 2007 if ( aDay.equal( today )) std::cout << "aDay and tomorrow are equal \n"; // OUT: } Exercise Write function Date nextDate() which returns the date after the receiver without affecting the receiver. Test the function. C++ the Object Based Paradigm, page: 11 The previous example demonstrates  The body of a function defined in C1 as t1 f1(params)is indicated by t1 C1::f1(params).  anObj.f1(...) invokes the member function f1 for anObj; the function has access to all members of the object.  The body of a function defined in C1 has access to all fields and methods defined in C1; eg day means the day field of receiver.  Assignment (=) is defined for all objects (unless overridden by programmer – more later). Its semantics is  comparison (==) is not defined for objects - unless explicitly declared for specific class by programmer.  this is an implicit argument to all member functions; it is a pointer to the object for which the function is invoked; day is a shorthand for this->day.

C++ the Object Based Paradigm, page: 12

Constructors – Motivation

The problem: not all integer values make sense for the data

members of a Date object. For example, 44/-7/77 is not an

appropriate date, neither is 29/02/1997.

First Solution: provide an initialization function, as in

class Date{

public:

int year, month, day;

void init(int, int, int);

… };

void Date::init(int d, int m, int y)

{ if ( d<1 || d>31 )

{cout<12 )

{cout <2000 )

C++ the Object Based Paradigm, page: 13

{cout <31 )

{cout<12 )

{cout <3000 )

C++ the Object Based Paradigm, page: 15

{cout <print(); // OUT: 11 / 1 / 1996

// Date someDay;

// compiler error message:

// no appropriate default constructor

available

// Date* aday = new Date;

C++ the Object Based Paradigm, page: 16

// compiler error message:

// no appropriate default constructor

available

}

The previous example demonstrates

 No return type, no return anObj in constructors

 If a class has a constructor, all objects of that class will be
initialised

 If the constructor requires arguments, they must be supplied.

 Constructors called whenever a new object is declared or
created.

Good C++ Programming Practice
Every class should have (at least one) constructor, and (probably) a

destructor (destructors discussed later).

C++ the Object Based Paradigm, page: 17

Dynamic Objects – pointers revisited

#include

#include “Date.h”

using namespace std;

int main(){

Date *aDate, *bDate;

aDate = new Date(5, 11, 1996);

bDate = new Date(5, 11, 1996);

aDate->print(); // OUT: 5 / 11 / 1996

bDate->print(); // OUT: 5 / 11 / 1996

if ( aDate == bDate )

cout << "aDate, bDate are same \n"; else cout << "aDate, bDate are not same\n"; // OUT: aDate, bDate are not same if ( aDate->equal(*bDate))

cout << "aDate, bDate are equal\n"; else cout << "aDate, bDate are not equal\n"; C++ the Object Based Paradigm, page: 18 // OUT: aDate, bDate are equal (*aDate).next(); aDate->print(); // OUT: 6 / 11 / 1996

bDate->print(); // OUT: 5 / 11 / 1996

bDate = aDate;

aDate->print(); // OUT: 6 / 11 / 1996

bDate->print(); // OUT: 6 / 11 / 1996

aDate->next();

aDate->print(); // OUT: 7 / 11 / 1996

bDate->print(); // OUT: 7 / 11 / 1996

if ( aDate == bDate )

cout << "aDate and bDate are same\n"; // OUT: aDate and bDate are same } C++ the Object Based Paradigm, page: 19 The previous example demonstrates  pointers are declared through ClassA* aPointer  new ClassA creates at run time a new object of ClassA  (*aPointer) dereferences aPointer; it is of type ClassA  aPointer->aMember is syntactic sugar for
(*aPointer).aMember

 ClassA may not appear where ClassA* expected, nor may

ClassA* appear where ClassA expected.

 assignment (=) for pointers is defined; its semantics is

it introduces aliasing

 comparison (==) for pointers is defined; its semantics is

C++ the Object Based Paradigm, page: 20

Are classes necessary?

 One could have used a group of variables instead:
void next(int& day, int& month, int& year)

{ day++ ;

if ( day==32 ) { day = 1; month++;};

if (month==13) {month=1; year++;}; }

int todayD, todayM, todayYear;

int tomorrowD, tomorrowM, tomorrowY;

next(todayD, todayM, todayYear)

This would lead to …

 One could have used a struct instead (by definition, a

struct is a class with all its members public).

However, …

C++ the Object Based Paradigm, page: 21

Are member functions necessary?

One could have used functions instead:

class Date{

public:

int year, month, day; };

void next(Date& aDate)

{ if ( aDate.day==31 ) { aDate.day = 1;

if (aDate.month==12)

{aDate.month=1; aDate.year++};

aDate.month++ }

else { aDate.day++ } };

Date td;

td.day = 26; td.month = 11; td.year = 1996;

next( td );

But this would lead to:

C++ the Object Based Paradigm, page: 22

References

References are alternative names for objects

 X& means reference to X

 A reference must be initialised

 Initialization is different from assignment.

 Assignment to a reference, or any operation invoked on the
reference does not affect the reference; it affects the object

referred to.

#include

#include “Date.h”

int main(){

Date today(25,11,2001);

Date tomorrow(31,12,2002);

today.print();

C++ the Object Based Paradigm, page: 23

// OUT: 25 / 11 / 2001

tomorrow.print();

// OUT: 31 / 12 / 2002

Date &rDate = today;

// Date &r1Date; r1Date = today;

today.print();

// OUT: 25 / 11 / 2001

rDate.print();

// OUT: 25 / 11 / 2001

today.next(); rDate.next();

today.print();

// OUT: 27 / 11 / 2001

rDate.print();

// OUT: 27 / 11 / 2001

tomorrow.print();

// OUT: 31 / 12 / 2002

rDate = tomorrow;

C++ the Object Based Paradigm, page: 24

today.next(); rDate.next();

today.print();

// OUT: 2 / 1 / 2003

rDate.print();

// OUT: 2 / 1 / 2003

tomorrow.print();

// OUT: 31 / 12 / 2002

tomorrow.next();

today.print();

// OUT: 2 / 1 / 2003

rDate.print();

// OUT: 2 / 1 / 2003

tomorrow.print();

// OUT: 1 / 1 / 2003

}

C++ the Object Based Paradigm, page: 25

References are similar to pointers in that:

References are different from pointers in that:

The main use for references is in specifying arguments and return

values for functions and operators.

For example, the Date class should have been declared as:

//in file Date.h

class Date{

public:

int year, month, day;

. . .

int equal(Date&);

};

because

Then, the implementation of class Date would be:

C++ the Object Based Paradigm, page: 26

//in file Date.cpp

int Date::equal(Date& aDate)

{ return (aDate.day == day)

&& ( aDate.month == month ) )

&& ( aDate.year == year); }

Then, the use of class Date would be modified as follows:

// in file main.cpp

int main(){. . .

Date today, tomorrow;

. . .

if (tomorrow.equal(today))

cout << "today and tomorrow are \n"; . . . } C++ the Object Based Paradigm, page: 27 References, Pointers and Call by Value Parameter Passing  actual parameters may be affected through the use of pointers or references to them // consolidates param passing, references and pointers void f1(Date aDate){ aDate.next(); } void f2(Date* pDate){ pDate->next(); }

void f3(Date& rDate){ rDate.next(); }

int main(){

Date d( 2, 12, 2222);

Date* p = new Date( 15, 1, 1919);

Date& r = d;

d.print(); // OUT: 2 / 12 / 2222

C++ the Object Based Paradigm, page: 28

p->print(); // OUT: 15 / 1 / 1919

r.print(); // OUT: 2 / 12 / 2222

f1(d);

d.print(); // OUT: 2 / 12 / 2222

f1(*p);

p->print(); // OUT: 15 / 1 / 1919

f1(r);

r.print(); // OUT: 2 / 12 / 2222

f2(&d);

d.print(); // OUT: 3 / 12 / 2222

f2(p);

p->print(); // OUT: 16 / 1 / 1919

f2(&r);

r.print(); // OUT: 4 / 12 / 2222

f3(d);

d.print(); // OUT: 5 / 12 / 2222

f3(*p);

C++ the Object Based Paradigm, page: 29

p->print(); // OUT: 17 / 1 / 1919

f3(r);

r.print(); // OUT: 6 / 12 / 2222

d.print(); // OUT: 6 / 12 / 2222

p->print(); // OUT: 17 / 1 / 1919

r.print(); // OUT: 6 / 12 / 2222

}

The previous example demonstrates

 &anObj is the address of anObj, it has type T* if anObj

has type T

 *aPnter derefences aPnter, and it has type T if aPnter

has type T*.

 The function f1 never affects its actual parameter

 The functions f2, f3 have very similar effect. They differ in

C++ the Object Based Paradigm, page: 30

 One should declare parameters of type T as

 T& when

 T* when

 T when

 Actually, the functions f2, f3 do not modify their

parameters either: f2 does not affect p, it modifies the object

pointed at by p; also, f3 does not affect r, it modifies the

object referenced by r.

C++ the Object Based Paradigm, page: 31

Constructors and Destructors

Special member functions are:

 Constructors: … as discussed earlier …

 Destructors: control object destruction; they reverse the effect of
constructors, and release memory. They too look like member

functions with the same name as the class, preceded by ~.

Constructors called whenever a new object is declared or created.

Destructors called implicitly whenever an object gets out of scope.

They may also be called explicitly by anObj.~ClassName.

Also, delete aPntr invokes the destructor for *aPntr.

C++ the Object Based Paradigm, page: 32

// in file Book.h

class Book{

public:

char* title;

int serialNumber;

Book(char*);

~Book(); };

extern int bookCounter ;

// in file Book.cpp

#include

#include

#include “Book.h”

using namespace std;

Book::Book(char *t)

{ title = new char [strlen(t)+1];

strcpy(title,t); serialNumber = ++bookCounter;

cout << " constr " << title C++ the Object Based Paradigm, page: 33 << " at "<< serialNumber << endl; } Book::~Book() { cout << " del " << title << " from " << serialNumber <<"; BC = " << --bookCounter << endl; delete [] title; }; // in file Book.cpp #include

#include

#include “Book.h”

using namespace std;

int main( ){

Book b1(“Seagull”);

// OUT: Seagull at 1

Book *b2, *b3 ;

// OUT:

C++ the Object Based Paradigm, page: 34

{ Book b4(“Iron Mask”);

// OUT: constr Iron Mask at 2

b2 = new Book(“Moonstone”);

// OUT: constr Moonstone at 3

Book *b5 = new Book(“Tom Sawyer”);

// OUT: constr Tom Sawyer at 4

} // OUT: del Iron Mask from 2; BC = 3

b2 = new Book(“Polyanna”);

// OUT: constr Polyanna at 4

b2 = new Book(“Shogun”);

// OUT: constr Shogun at 5

b3 = b2;

// OUT:

delete b3;

// OUT: del Shogun from 5; BC = 4

cout << "Now " << bookCounter << " books left \n"; return 1; } // OUT: del Seagull from 1; BC = 3 So, we have memory leaks! C++ the Object Based Paradigm, page: 35 Good C++ Programming Practice Every class should have (at least one) constructor, and (probably) a destructor  Constructors should ensure the integrity of the objects produced  It is the programmer’s responsibility to destroy dynamically created objects  It is the system’s responsibility to destroy declared (static or local) objects. C++ the Object Based Paradigm, page: 36 Motivating Private Members Constructors alone cannot guarantee the integrity of data: class Date{ public: int year, month, day; Date(int, int, int); void next(); Date nextDate(); bool equal(Date); } // some other part of the program Date myBirthday(29,2,1940); . . . myBirthday.year++ // very bad! C++ the Object Based Paradigm, page: 37 Private / Public / Protected Members Members may have one of three levels of program access:  public may be accessed anywhere they are within scope.  protected  private may only be accessed by member functions of the class or by friends of the class. Public members describe the interface of an ADT; private members describe its implementation. Members are private by default. Therefore class Date{ int year, month, day; public: Date(int, int, int); void next(); } } C++ the Object Based Paradigm, page: 38 is a shorthand for class Date{ private: int year, month, day; public: Date(int, int, int); void next(); } An Exercise in Private / Public Members class A{ int j; int f(int y){ return ++k; }; public: int k; int g(int x){ return --j; }; void print(){ cout << " j= " << j << ", k= " << k << endl;}; int compare(A z) { return (k==z.k)&&(j==z.j)&& C++ the Object Based Paradigm, page: 39 (z.f(1)==g(5)); }; A(int x, int y){ j=x; k=y; }; } void f(A x){ // x.j++ ; // compiler error: cannot access private member x.k++;; // cout << x.f(1) << endl; // compiler error: cannot access private member cout << "x.g(2)= " << x.g(2) << endl; } int main(void){ A a1(10,20), a2(30,40); a1.print(); f(a1); // a1.f(3); // compiler error: cannot access private member a1.g(5); a1.compare(a2); return 0;} C++ the Object Based Paradigm, page: 40 The previous example demonstrates:  member functions may access all members of class, even of those that do not belong to the object currently executing the function, e.g. z.f(1) in A::compare().  other functions may only access public members.  inline expansion of functions, e.g. A::compare(). . Good C++ Programming Practice  Make private as many members as possible.  Data members are usually private.  Some member functions should be private too.  Motto: disseminate information on a “need to know” basis. C++ the Object Based Paradigm, page: 41 Given program P which compiles and runs successfully, take P’=P-privAnnotations annotations. Does then P’ compile? run? If it runs, what result does it produce? Given program P which compiles and runs successfully, take P’=P+privAnnotations annotations. Does then P’ compile? run? If it runs, what result does it produce? C++ the Object Based Paradigm, page: 42 Friends A non-member function that is allowed access to the private part of a class is a friend of the class. A function is made a friend of a class by a friend declaration: class C2; class C1; class C2{ int j; public: friend int f(C1&,C2&); int g(C1& ); C2(int l){ j=l }; }; class C1{ int i; public: C1(int l){ i=l }; friend int f(C1&,C2&); friend int C2::g(C1&); }; int f(C1& aC1, C2& aC2) {return aC1.i*aC2.j;} C++ the Object Based Paradigm, page: 43 int C2::g(C1& aC1) {return aC1.i* j; } int main(void) { C1 a(7); C2 b(3); … f(a,b)+b.g(a) return 0;} The previous example demonstrates  incomplete class declarations used for mutually recursive class definitions (e.g. class C1; class C2;).  friends can be functions (e.g. int f()) or member functions from other classes (e.g. C2::g(C1&)).  inline expansion of functions (e.g. C2::C2(int)). C++ the Object Based Paradigm, page: 44 If a class is declared a friend of another class, then all the member functions of the former are friends of the latter: class C3; class C4; class C3{ int j; public: C3(int i){j=i;}; friend class C4; }; class C4{ public: int g(C3& aC3); { return 2*aC3.j;}; }; C++ the Object Based Paradigm, page: 45 Types and Classes class Cowboy{ void draw(); void move(Point);} class Circle{ void draw(); void move(Point);} Cowboy jim; Circle c; // jim = c; class A{ int x; }; int anInt, char aChar; A anA; anInt = aChar; // anInt = anA; The above example demonstrates:  Fundamental types can be mixed freely in assignment and expressions.  Structure types are different, even if they have the same members.  Structure types are different from fundamental types. C++ the Object Based Paradigm, page: 46 Static Members A data or function member of a class may be declared static. There is only one copy of a static data member, shared by all objects of the class in the program. A static member of class c1 can be referred to as c1::mem, that is, independently of any object. In UML class diagrams, attributes or operations that affect the class as a whole, are underlined C++ the Object Based Paradigm, page: 47 For instance, instead of a global variable BookCounter from earlier, use a static data member, BookCounter //file Book.h class Book{ char* title; static int counter; int serialNumber; public: Book(char*); ~Book(); static void printNumberBooks();} //file Book.cpp #include …. int Book::counter = 0 ; C++ the Object Based Paradigm, page: 48 void Book::printNumberBooks() { cout << "== there are " << counter << " Books \n"; } Book::Book(char *t) { . . . ++counter . . .} Book::~Book(){ . . . --counter . . . }; //in file main.h #include …. int main( ){ // printNumberBooks(); Book::printNumberBooks(); // … as earlier … … ... return 0; } C++ the Object Based Paradigm, page: 49 The previous example demonstrates  static members accessible from member functions; also, from other classes or main program if public, or friends.  static member function called by ClassName::func(…);  static variables may be accessed by ClassName::varName  body of static member function indicated by resultType ClassName::func( . .){ … }.  static data members have to be initialized by type ClassName::dataName = … notice, that static is not repeated here  static data members similar, but not identical to C static variables  static members preferable to global variables or methods because: C++ the Object Based Paradigm, page: 50 Overloading Different functions have typically different names, but for functions performing similar tasks on different types of objects it is best if they have the same name. When their argument types are different, the compiler can distinguish them anyway and choose the right function to call. For example: class Date{ int year, month, day; public: Date( int, int, int); Date( int ); Date(int, char, int); void next(); void next(int); } A program with overloading can be transformed into a program without overloading through C++ the Object Based Paradigm, page: 51 //exercise for overloaded functions int f(int i1, int i2) { return 1; }; int f(char c1, char c2) { return 2; }; int f(int i1, char c1) { return 3; }; int f(char c1, int c2) { return 4; }; // The following are not overloaded class A{ public: int f(char c){ return 5; }; }; class B{ public: int f(char c){ return 6; }; }; // The following are overloaded class C{ public: int f(A x){ return 7; }; int f(B x){ return 8; }; }; C++ the Object Based Paradigm, page: 52 int main(){ int x, y; char u, v; A anA; B aB; C aC; cout << f(x,y) << endl; // OUT: 1 cout << f(u,v) << endl; // OUT: 2 cout << f(x,u) << endl; // OUT: 3 cout << f(u,y) << endl; // OUT: 4 cout << anA.f(u) << endl; // OUT: 5 cout << aB.f(u) << endl; // OUT: 6 cout << aC.f(anA) << endl; // OUT: 7 cout << aC.f(aB) << endl; // OUT: 8 } The previous example demonstrates:  member functions from same class with same identifier and different argument types overload each other.  non-member functions with same identifier and different argument types overload each other.  overloading resolution based on actual parameter types, ie at compile time (statically) C++ the Object Based Paradigm, page: 53 Constants Adding the keyword const to the declaration of an entity makes it a constant rather than a variable. The value of constants may not be modified; therefore constants must be initialised. Rationale for constants:  for the programmer  for the compiler Constants restrict the way entities may be used. We may have :  constant entities of fundamental types  constant objects  constant parameters  constant result types  constant data members  constant member functions C++ the Object Based Paradigm, page: 54 class A{ const int i; int k; public: A(int l,int m); void f1(int l) void f2(int l) const; }; A::A(int l,int m):i(l){ k=m; }; void A::f1(int l) { k=k+i+1; /* i=i-1; */ }; void A::f2(int l) const { int m = k+i+1; /* k=k+i+1; i=i-1; */}; void h1(const A& anA, int l) { anA.f2(l); /* anA.f1(8); */ }; C++ the Object Based Paradigm, page: 55 void h2( A& anA, int l) { anA.f1(l); anA.f2(2*l); }; int main(void){ const int constInt = 44; const A aConst(1,1); // constInt = 33; // const int anotherConst; // aConst.f1(3); // h2( aConst, 5); cout << aConst< += -= *= /= %=

&= |= << >> >>= <<= == != < = >= && || ++ — ->* , ->

[] ()

new delete

C++ the Object Based Paradigm, page: 58

For example, operators for complex numbers.
// file Compl.h

#include

using namespace std;

class Compl{

double re, im;

public:

Compl (double,double);

friend Compl operator+

(const Compl&, const Compl&);

friend Compl operator-

(const Compl&, const Compl&);

…… // similar for operators -, /, *

friend ostream& operator<< (ostream&, const Compl&); }; // file Compl.cpp #include “Complex.h” Compl operator+ (const Compl&, const Compl&) { return Compl( z1.re+z2.re), z1.im+z2.im));} C++ the Object Based Paradigm, page: 59 ...... // similar for the operators -, /, * ostream& operator<< (ostream&, const Compl&) { o << "(r " << c.re << ", i "<< c.im << " )\n"; return o;}; Compl::Compl(double r, double i) {re=r; im=i;}; // file main.cpp #include “Complex.h” int main(){ Compl z1(2.2,4.4); Compl z2(1.1,3.3); cout << "z1 =" << z1 << "z2 =" << z2 ; // OUT: z1 = ( 2.2, 4.4 ) // OUT: z2 = ( 1.1, 3.3 ) cout << (z1+z2); // OUT: ( 3.3, 7.7 ) cout << (z1-z2); // OUT: ( 1.1, 1.1 ) cout << (z1*z2); // OUT: ( 2.42, 14.52 ) cout << (z1/z2); // OUT: ( 2, 1.33333 ) cout << ((z1/z2)+(z1*z2))-z1; // OUT: ( 2.22, 11.4533 ) return 1; } C++ the Object Based Paradigm, page: 60 User defined operators are syntactic sugar. They could be replaced by 1) or by 2) Using 1) the class Compl would be defined as class Compl{ double re, im; public: Compl (double,double); }; and then ((z1/z2)+(z1*z2))-z1 would be represented as C++ the Object Based Paradigm, page: 61 Using the class Compl would be defined as class Compl{ double re, im; public: Compl (double,double); }; and then ((z1/z2)+(z1*z2))-z1 would be represented as C++ the Object Based Paradigm, page: 62 The advantage of operators is Aside: Thus, knowing that << has been overloaded, as ostream& operator<<1 (ostream&, string) ostream& operator<<2 (ostream&, double) ostream& operator<<3 (ostream&, char) ostream& operator<<3 (ostream&, const Compl&) we can analyze the expression cout << " z1+z2 =" << z1+z2 << ‘\n’ ; C++ the Object Based Paradigm, page: 63 Operators summary Operators may either be global operators or member functions. In the previous example, all operators were Binary operators may be defined through global operators with two arguments, or through member functions with one argument. Unary (prefix) operators may be defined through global operators with one argument, or through member functions without argument. NOTE The new ISO standard expects some operators to take constant reference parameters, e.g. friend Compl operator+ (const Compl&, const Compl&) or Compl operator+ (const Compl&) C++ the Object Based Paradigm, page: 64 // demonstration of Operators class A{ int i; public: A(int l); friend A operator+ (const A&, const A&); A operator- (const A&) const; friend A& operator++( A&); A& operator--(); friend ostream& operator<< (ostream&, const A&); }; A::A(int l) {i =l;} A operator+ (const A& a1, const A& a2) { return A(a1.i+a2.i); }; A A::operator- (const A& anA) const { return A(i-anA.i); }; C++ the Object Based Paradigm, page: 65 A& operator++( A& a1) { a1.i=a1.i+4; return a1; }; A& A::operator--( ) { i= i-4; return *this; }; ostream& operator<< (ostream& o, const A& anA) { return o << "A(" << anA.i << ")"; }; int main(void){ A anA1(5), anA2(6); cout << "anA1=" <dataMember <=> dataMember

this ->memFunc(…) <=> memFunc(…)

For example,
class A{

int i;

public:

A(int i){ this->i= i; };

void f(){ this->i=3; this->f(); f(); }

/* this =new A(4); */ };

}

void h(A& anA){anA.f(); /* this->f(); */ };

C++ the Object Based Paradigm, page: 92

The previous example demonstrates:

 this->memFnct(params) equiv memFnct(params),

e.g. this->f() equivalent to f().

 this->dataMem equivalent to dataMem,

e.g. this->i equivalent to i.

 this only available inside a member function,

e.g. this->f() illegal in h.

 assignments to this illegal,

e.g. in the body of f.

In the previous, this was dispensable. But in the case of

 functCall( ..,this, ..)

 … = this;

the identifier this is indispensable.

An example, where this is indispensable, is a doubly linked list:

C++ the Object Based Paradigm, page: 93

Doubly Linked Lists

6 8 1412

(Note: above is NOT an UML object diagram)

Doubly linked lists

 contain a sequence of numbers

 may insert a number at the end or after another number

 may be printed forwards or backwards

insert(int)

insertAfter(int,int)

isEmpty(): bool

length(): int

remove(int)

printForwards()

printBackwards()

DLinkList

C++ the Object Based Paradigm, page: 94

We shall take this opportunity to discuss

 use of this for the implementation of class DLinkList

 design of ADTs as apparent in this example

 test driven development

 breaking up program into header, body and main files

 lists

 mapping UML to C++ (roughly)

C++ the Object Based Paradigm, page: 95

Test driven development: Consider possible cases, and when there is a

leeway, decide the expected behaviour. This can be reflected in a “test

plan” for the particular class. For example, indicating the possibilities in

italics, and the choices by strike-through:

1) are empty lists possible? yes, no

2) a list with one element

3) a list with several elements

4) add an element into an empty list

5) add an element into a nonempty list

6) insert element after another that exists in list

7) insert element after a non-existing: void, error, insert at end

8) remove an element that is in the list

9) remove an element that is not in the list: void, error

10) remove an element from the empty list: void, error

C++ the Object Based Paradigm, page: 96

These decisions will be reflected in header files and in test function:

// file DLinkList.h
#include

using namespace std;

#include “DLink.h”

class DLinkList{

DLink *firstLink; // first link of chain

public:

DLinkList();

// 1: creates new, empty doubly linked list

// constructor reflects decision on 1)

void insert(int x);

// inserts a new link with x at the

// end of the list

void insertAfter(int x, int y);

C++ the Object Based Paradigm, page: 97

// inserts new link with x in list

// after y;

// 7: y not in list, then nothing inserted

bool isEmpty() const;

// true if receiver is an empty list

int length() const;

// number of elements in the list

void remove(int x);

// removes element containing x

// 9, 10: does nothing if x not in list

friend ostream&

operator<<(ostream&, const DLinkList&); // prints list forwards friend ostream& operator>>(ostream&, const DLinkList&);

}

C++ the Object Based Paradigm, page: 98

And the main program, together with expected output

// file DLLMain.cpp
#include “DLinkList.h”

int main(){

DLinkList list;

// 1: printing an empty list

cout << list ; // out --- // 2: inserting the first element // 2: printing list with one element list.insert(6); cout << list << endl >> list ;

// out 6 – —

// out 6 – —

// 3: inserting 8, 12, 14

list.insert(8); list.insert(12); list.insert(14);

cout << list << endl >> list ;

// out 6 – 8 – 12 – 14 – —

// out 14 – 12 – 8 – 6 – —

C++ the Object Based Paradigm, page: 99

// 6: inserting 10 after 8

list.insertAfter(10, 8);

cout << list << endl >> list ;

// out 6 – 8 – 10 – 12 – 14 – —

// out 14 – 12 – 10 – 8 – 6 – —

// 7: inserting 100 after 500

list.insertAfter(100, 500);

cout << list << endl >> list ;

// out 6 – 8 – 10 – 12 – 14 – —

// out 14 – 12 – 10 – 8 – 6 – —

// 9: removing an element that is not in list

list.remove(500);

cout << list << endl >> list ;

// out 6 – 8 – 10 – 12 – 14 – —

// out 14 – 12 – 10 – 8 – 6 – —

// removing an element from middle of list

list.remove(10);

cout << list << endl >> list ;

// out 6 – 8 – 12 – 14 – —

C++ the Object Based Paradigm, page: 100

// out 14 – 12 – 8 – 6 – —

// 8: removing the first element

list.remove(6);

cout << list << endl >> list ;

// out 8 – 12 – 14 – —

// out 14 – 12 – 8 – —

// 8: removing the last element

list.remove(14);

cout << list << endl >> list ;

// out 8 – 12 – —

// out 12 – 8 – —

// 8: removing all elements

list.remove(8); list.remove(12);

cout << list << endl >> list ;

// out —

// out —

// 9: removing from empty list

list.remove(8); list.remove(100);

cout << list << endl >> list ;

C++ the Object Based Paradigm, page: 101

// out —

// out —

return 1;}

C++ the Object Based Paradigm, page: 102

Representation of DlinkList.

We can now consider the represenation of class DlinkList.

The first question id the representation of its object.

Obviously, a non-empty list will be represented through doubly

chained objects, as in

6 8 1412

(Note: above is NOT an UML object diagram)

But what about the representation of the empty list? In C, it could

be represented as the null pointer, but in C++ it can’t (why?).

C++ the Object Based Paradigm, page: 103

The standard solution is to distinguish between the list object (of

class DlinkList) and the list components (of class Dlink)

Thus, a doubly linked list with 6, 8, 12 and 14 will be represented as:

(DLink)

contents: 6

next:

prev:

(DLinkList)

firstLink:

(DLink)

contents: 8

next:

prev:

(DLink)

contents: 12

next:

prev:

(DLink)

contents: 14

next:

prev:

whereas an empty doubly linked list will be represented as:

(DLinkList)

firstLink:

( where the two above are “almost” UML object diagrams)

C++ the Object Based Paradigm, page: 104

Doubly linked lists are represented by a header (DLinkList) and

a chain of links (DLink)

insert(int)

insertAfter(int,int)
isEmpty(): bool

length(): int

remove(int)

printForwards()

printBackwards()

DLinkList

next

contents : int

insert(int)

find(int): DLink*

isEmpty(): bool
length(): int

printForwards()

printBackwards()

DLink

previous

firstLink

The above gives the following decomposition into files:

DlinkList.h, DlinkList.cpp,

Dlink.h, Dlink.cpp,

DLLMain.cpp.

The association firstLink was represented as a pointer to a DLink

in DLinkList.h. We shall also represent the associations next and

previous as pointer to DLinks. Thus:

C++ the Object Based Paradigm, page: 105

Implementing the classes

// file DLink.h
#include

using namespace std;

class DLinkList;

class DLink{ // the link

int contents;

// the integer in the link

DLink *next, *prev;

// pointers to the next and previous links

// of the chain, possibly nil

DLink(int);

~DLink();

void insertAfterThis(int);

// creates a new link containing x,

C++ the Object Based Paradigm, page: 106

// and inserts after current link

DLink* lastLink();

// returns the last link in the chain

DLink* find(int x);

// returns pointer to link with contents x

// or nil, if no such link found

int length() const;

// returns number of links in the chain

friend ostream&

operator<<(ostream&, const DLink&); // prints list "forwards" friend ostream& operator>>(ostream&, const DLink&);

// prints list “backwards”

C++ the Object Based Paradigm, page: 107

friend ostream&

operator<<(ostream&, const DLinkList&); // prints list "forwards" friend ostream& operator>>(ostream&, const DLinkList&);

// prints list “backwards”

friend class DLinkList; };

DLink* const nil = 0; // the null DLink pointer

Notice  all members are private,

 class DLinkList a friend,

 four friend operations,

 the null DLink pointer.

C++ the Object Based Paradigm, page: 108

In general, the member functions of DLinkList check whether

the list is empty, and if not, they delegate the request to

firstLink or lastLink() (ie the class DLink)

// file DLinkList.cpp
#include “DLink.h”

DLinkList::DLinkList() { firstLink = nil; };

void DLinkList::insert(int x)

{ if (firstLink==nil) // empty list

{ firstLink = new DLink(x);}

else { (firstLink->

lastLink())->insertAfterThis(x);};}

bool DLinkList::isEmpty() const

{ return (firstLink==nil); }

C++ the Object Based Paradigm, page: 109

int DLinkList::length() const

{ if (firstLink==nil) { return 0; }

else { return firstLink->length(); }; }

void DLinkList::insertAfter(int x, int y)

{ if (firstLink==nil) { return; } // empty list

else

{ DLink* theLink = firstLink->find(y);

if (theLink ==nil) // y not in list

{ return; } // 7: do nothing

else { theLink->insertAfterThis(x);} } }

void DLinkList::remove(int x)

{ if (firstLink==nil) // empty list

{ return; } // 10: do nothing

else

{ DLink* theLink=firstLink->find(x);

if (theLink ==nil) // not found

{ return; } // 9: do nothing

else

C++ the Object Based Paradigm, page: 110

{ if (theLink==firstLink)

// it is the first element

firstLink=theLink->next;

delete theLink; } }}

ostream& operator<<(ostream& o, const DLinkList& l) { if (l.firstLink==nil) { o << " ---\n";} else { o << *l.firstLink ; }; return o;} ostream& operator>>(ostream& o, const DLinkList& l)

{ if (l.firstLink==nil) { o << " ---\n"; } else { o >> *l.firstLink->lastLink();};

return o; }

C++ the Object Based Paradigm, page: 111

The member functions of Dlink are responsible for navigating

forwards or backwards through the link structure, and are responsible

for maintaining the forwars/backwards links when updating the link

structure

// file DLink.cpp
#include “DLink.h”

DLink::DLink(int x)

{ next=nil; prev=nil; contents=x;}

DLink::~DLink()

{ DLink* oldPrev= prev; DLink* oldNext= next;

if (!(oldPrev==nil)) oldPrev->next = oldNext;

if (!(oldNext==nil)) oldNext->prev = oldPrev;}

DLink* DLink::lastLink()

{ if (next==nil) { return this;}

else {return next->lastLink(); } }

C++ the Object Based Paradigm, page: 112

void DLink::insertAfterThis(int x)

{ DLink* oldNextLink = next;

DLink* newLink= new DLink(x);

next = newLink;

newLink->prev = this;

if (oldNextLink!=nil)

oldNextLink->prev = newLink;

newLink->next = oldNextLink; }

ostream& operator<<(ostream& o, const DLink& l) { o << l.contents << " - "; if (l.next==nil){ o<< "---\n"; return o;} else { o << (*(l.next)) ; return o; };} ostream& operator>>(ostream& o, const DLink& l)

{ o << l.contents << " - "; if (l.prev==nil){ o<< "---\n"; return o;} else { o >> (*(l.prev)) ; return o; };}

C++ the Object Based Paradigm, page: 113

DLink* DLink::find(int x)

{ if ( contents == x) { return this;}

else { if (next == nil) { return nil; }

else { return next->find(x);}; } }

int DLink::length() const

{ if ( next== nil) { return 1;}

else { return 1 + next->length();}; }

This example demonstrates (among other things):

 use of this in body of DLink::inserAfterThis(…),

DLink::lastLink() and DLink::find(int)

 pointer structures

 “delegation” and object “collaboration”

 clever use of destructors

 recursive definitions

C++ the Object Based Paradigm, page: 114

The Object Based Features in C++ – Summary

 classes

 data members

 member functions

 static members

 constructors, destructors

 this

 private/public/protected members

 name type equivalence for composite types

 function overloading, default parameters, constants

 operator overloading

 use of pointers, references

 member functions vs global functions

C++ the Object Based Paradigm, page: 115

The “Imperial MSc C++ Programming Life Cycle”

1) Read problem description,

2) Draw the UML object model class diagram,

3) “Design’’ C++ program (i.e. headers, main function, compile main)

4) For each class Classi:

4a) specify behaviour of each member function, especially for border cases

4b) write a static Classi::testMe() function which demonstrates behaviour

of all member functions;

4c) write member function bodies;

4d) test using Classi::testMe().

5) Integrate and test.

6) If specification not met, continue at point 1.

Border cases are the “unexpected” cases. For example, asking the length of an empty list,

receiving a negative input where a positive was expected.

NEVER jeopardise good design in order to get the program to run.

C++ the Object Based Paradigm, page: 116

From UML to C++

UML class diagram =

 classes with attributes and operations

 associations between classes

 inheritance structure

UML is a high level description: it is concerned with the modelling

of some situation, and not with how to store/represent the

information

C++ is a “middle” level description: among other things, it is

concerned with how to store/represent the information

C++ the Object Based Paradigm, page: 117

UML Classes, Attributes and Operations

class: group of objects with similar properties.

attributes: data values held by objects in a class; they have

fundamental type.

operations: services that my be supplied by object.

Employee

salary: double

age: int

payrise(double)

birthday()

In general: UML class —–> C++

attribute —–> C++

operation —–> C++

C++ the Object Based Paradigm, page: 118

Remember:

 First the UML object model class diagram, then the C++ design.

 The C++ design may contain more functions/data members than the
UML class diagram.

 The C++ design may contain more classes than the UML class
diagram.

 The UML class diagram may not express all aspects of specification.

Read on in the next part of the course: C++ the Object Oriented

Paradigm