• No results found

CS 101:

N/A
N/A
Protected

Academic year: 2022

Share "CS 101:"

Copied!
54
0
0

Loading.... (view fulltext now)

Full text

(1)

CS 101:

Computer Programming and Utilization

Puru

with

CS101 TAs and Staff

Course webpage: https://www.cse.iitb.ac.in/~cs101/

Lecture 20: C++ and object oriented programming

(2)

Object Oriented Programming

A methodology for designing programs

(3)

The C++ structure

• Member variables

− Basic facility provided in C++ to conveniently gather together information associated with an entity

− Inherited from the C language

• Member functions

− New feature introduced in C++

− Actions/operations that effect the entity

− User defined data type with variables and functions

(4)

Nested structures (structure is a data type!)

struct Point{

double x,y;

};

struct Disk{

Point center; // contains Point double radius;

};

Disk d;

d.radius = 10;

d.center = {15, 20};

// sets the x {member of center member of d

(5)

The Complete Definition of V3

struct V3{

double x, y, z;

double length const(){

return sqrt(x*x + y*y + z*z);

}

V3 sum const(V3 b){

V3 v;

v.x = x+b.x; v.y=y+b.y; v.z=z+b.z;

return v;

}

V3 scale const(double f){

V3 v;

v.x = x*f; v.y = y*f; v.z = z*f;

return v;

} }

(6)

The Queue structure

const int N=100;

struct Queue{

int elements[N], nwaiting,front;

bool insert(int v){

}

bool remove(int &v){

} };

(7)

Main Program

int main(){

Queue q;

q.front = q.nWaiting = 0;

while(true){

char c; cin >> c;

if(c == ‘d’){

int driver; cin >> driver;

if(!q.insert(driver)) cout <<“Q is full\n”;

}

else if(c == ‘c’){

int driver;

if(!q.remove(driver)) cout <<“No taxiavailable”;

else cout <<“Assigning <<driver<< endl;

} }

(8)

Objects As Software Components

• A software component can be built around a struct

• Just as a hardware component is useful for building big hardware systems,

so is a software component for building large software systems

• A software component must be convenient to use, and also safe, i.e., help in preventing programming errors

(9)

Packaged software components

• Analogous idea for software:

– Make functionality associated with a struct available to the user only through member functions (control panel)

– Do not allow the user to directly access the data members inside a struct. (Just as a user cannot touch the circuitry) The user does not need to know what goes on inside

• If you build a better fridge but keep the control panel the same as the previous model, the user does not need to relearn how to use the new fridge

– If you build a better version of the struct, but keep the member functions the same, the programs that use the struct need not change

– Reusable, modular, abstract!

(10)

The modern version of a struct

• Designer of the struct decides what happens during execution of standard operations such as:

– Creation of the object – Assignment

– Passing the object to a function

– Returning the object from a function

– Destroying the object when it is not needed

(11)

C++ specifics of structures, classes and objects

• Constructors

• Copy Constructors

• Destructors

• Operator overloading

• Overloading the assignment operator

• Access control

• Classes

• Graphics and input/output classes

(12)

The Queue Struct in Taxi Dispatch

const int N=100;

struct queue{

int elements[N],

nWaiting,front;

bool insert(int v){

}

book remove(int &v){

}

• Once the queue is created, we expect it to be used only through the member

functions, insert and remove

• Ideally, we do not

expect/want elements, nWaiting, front to be directly accessed

(13)

Main Program Using Queue

int main(){

Queue q;

q.front = q.nWaiting = 0;

while(true){

char c; cin >> c;

if(c == ‘d’){

int driver; cin >> driver;

if(!q.insert(driver)) cout <<“Q is full\n”;

}

else if(c == ‘c’){

int driver;

if(!q.remove(driver)) . . .

• Main program does use q through operations insert and remove

• However, at the beginning, q.front and q.nWaiting are directly manipulated

• Against the philosophy of software packaging!

(14)

The Constructor member function

• In C++, the programmer can define a special member function called a constructor which will always be called when an instance of the struct is created

• A constructor has the same name as the struct, and has no return type

• Why useful?

(15)

The Constructor member function

• When q is created in the main program, the

constructor is called automatically

struct Queue{

int elements[N], front, nWaiting;

Queue(){ // constructor nWaiting = 0;

front = 0;

}

// other member functions };

int main(){

Queue q;

// no need to set

// q.nWaiting, q.front // to 0.

}

(16)

Constructors In General

struct A{

A(parameters){

… } };

int main(){

A x(arguments);

}

• Constructor can take arguments

• The creation of the object x in main can be thought of as

happening in two steps

– Memory is allocated for x

– The constructor is called on x with the given arguments

• Many constructors possible, provided they have different signatures

(17)

Another example: Constructor for V3

struct V3{

double x,y,z;

V3(){

x = y = z = 0;

}

V3(double a){

x = y = z = a;

} };

int main();

V3 v1(5), v2;

}

• When defining v1, an argument is given

• So the constructor taking a single argument is called. Thus each component of v1 is set to 5

• When defining v2, no argument is given.

• So the constructor taking no

arguments gets called. Thus each component of v2 is set to 0

(18)

Remarks

• If and only if programmer does not define a constructor, will C++

define a constructor which takes no arguments, and does nothing – If a constructor taking arguments is defined, you implicitly tell

C++ that you want programmers to give arguments.

– if some programmer does not give arguments, C++ will flag it as an error

– If you want both kinds of initialization, define both kinds of constructor

• A constructor that does not take arguments (defined programmer or by C++) is called a default constructor

• If you define an array of struct, each element is initialized using the default constructor

(19)

The Copy Constructor

• Suppose an object is passed by value to a function

– It must be copied to the variable denoted by the parameter

• Suppose an object is returned by a function

– The value returned must be copied to a temporary variable in the calling program

• By default the copying operations are implemented by copying each member of one object to the corresponding member of the other object

– this default behaviour can be changed by defining a copy constructor

(20)

Example

struct Queue{

int elements[N], nWaiting, front;

Queue(const Queue &source){ // Copy constructor front = source.front;

nWaiting = source.nWaiting;

for(int i=front, j=0; j<nWaiting; j++){

elements[i] = source.elements[i];

i = (i+1) % N;

} };

(21)

Copy Constructor in the Example

• The copy constructor must take a single reference argument:

the object which is to be copied

• Note that the argument to the copy constructor must be a

reference, otherwise the copy constructor will have to be called to copy the argument!

• This is will result in an unending recursion

• Member elements are not copied fully. Only the useful part of it is copied

– More efficient

• More interesting use later

struct Queue{

int elements[N], nWaiting, front;

Queue(const Queue &source){

// Copy constructor

……

} };

(22)

Tracking the use of constructors

struct Queue{

int copyID;

Queue(){

cout << "copyId=" << copyId;

}

Queue(const Queue &source){

copyId = source.copyId;

cout << "copyId=" << copyId;

} };

Queue updateQueue(Queue q){

q.copyId = 3;

return q;

}

int main(){

Queue q;

q.copyId = 1;

Queue r(q);

r.copyId = 2;

Queue z=updateQueue(r);

z.copyID = 4;

Queue a = z;

}

What will be printed?

(23)

Destructors

• When control goes out of a block in which a variable is defined, that variable is destroyed

– Memory allocated for that variable is reclaimed

• You can define a destructor function, which will get executed before the memory is reclaimed

(24)

Destructor Example

• If a queue that you have defined goes out of scope, it will be destroyed

• If the queue contains elements at the time of destruction, it is likely an error

• So you may want to print a message warning the user

• It is usually an error to call the destructor explicitly. It will be called automatically when an object is to be destroyed. It should not get called twice.

• More interesting uses of the destructor will be considered in later chapters.

(25)

Destructor Example

struct Queue{

int elements[N], nWaiting, front;

. . .

~Queue(){ //Destructor

if(nWaiting>0) cout << “Warning:”

<<“ non-empty queue being destroyed.”

<< endl;

} };

(26)

Operator Overloading

• In Mathematics, arithmetic operators are used with numbers, but also other objects

(27)

Operator Overloading

• In Mathematics, arithmetic operators are used with numbers, but also other objects such as vectors

• Something like this is also possible in C++!

• An expression such as x @ y where @ is any “infix” operator is considered by C++ to be equivalent to

x.operator@(y) in which operator@ is a member function

• If the member function operator@ is defined, then that is called to execute x @ y

(28)

Example: Arithmetic on V3 objects

struct V3{

double x, y, z;

V3(double a, double b, double c){

x=a; y=b; z=c;

}

V3 operator+(V3 b){ // adding two V3s return V3(x+b.x, y+b.y, z+b.z); // constructor call }

V3 operator*(double f){ // multiplying a V3 by f return V3(x*f, y*f, z*f); // constructor call

}

(29)

Using V3 Arithmetic

int main(){

V3 u(1,2,3), a(4,5,6), s;

double t=10;

s = u*t + a*t*t*0.5;

cout << s.x <<‘ ‘<< s.y << ‘ ‘<< s.z << endl;

}

(30)

Remarks

• Expression involving vectors can be made to look very much like what you studied in Physics/Mathematics

• Other operators can also be overloaded, including unary operators (see the book)

• Overload operators only if they have a natural interpretation for the struct in question

• Otherwise you will confuse the reader of your program

(31)

Pointers to Structures

• Disk d1={{2,3},4}, *dptr;

• *dptr is defined to have type Disk, so dptr is a pointer to a variable of type Disk

• Normal pointer operations are allowed on structure pointers

• dptr = &d1;

• (*dptr).radius = 5; //changes the radius of d1

• Operator ->

– (*x).y is same as x->y

• dptr->radius = 5; // same effect as above

(32)

Pointers as Structure Members

struct Disk2{

double radius;

Point *centerptr;

}

Point p={10,20};

Disk2 d;

d.centerptr = &p;

cout << d.centerptr->x << endl; // will print 10.

(33)

The this Pointer

So far, we have not provided a way to refer to the receiver itself inside the definition of a member function.

Within the body of a member function, the keyword this points to the receiver i.e., the struct on which the member function has been invoked.

Trivial use: write this->member instead of member directly struct V3{

double x, y, z;

double length(){

return sqrt(this->x * this->x + this->y * this->y

+ this->z * this->z);

} }

More interesting use later.

(34)

Overloading The Assignment Operator

• Normally if you assign one struct to another, each member of the rhs is copied to the corresponding member of the lhs

• You can change this behaviour by defining member function operator= for the struct

• A return type must be defined if you wish to allow chained assignments, i.e., v1 = v2 = v3; which means v1 = (v2 = v3);

– The operation must return a reference to the left hand side object

(35)

Example

struct Queue{

...

Queue& operator=(Queue &rhs){

front = rhs.front;

nWaiting = rhs.nWaiting;

for(int i=0; i<nWaiting; i++){

elements[i] = rhs.elements[i];

i = (i+1) % N;

}

return *this;

} };

// only the relevant elements are copied

(36)

Access Control

• It is possible to restrict access to members or member functions of a struct

• Members declared public: no restriction

• Members declared private: Can be accessed only inside the definition of the struct

Typical strategy

Declare all data members to be private, and some subset of function members to be public

(37)

Access Control Example

struct Queue{

private:

int elements[N], nWaiting, front;

public:

Queue(){ … } bool insert(int v){

..

}

bool remove(int &v){

..

} };

(38)

Remarks

• public:, private: : access specifiers

• An access specifier applies to all members defined following it, until another specifier is given

• Thus elements, nWaiting, front are private, while Queue(),

insert, remove are public

(39)

Remarks

• The default versions of the constructor, copy constructor, destructor, assignment operator are public

• If you specify any of these as private, then they cannot be invoked outside of the struct definition

• Thus if you make the copy constructor of a struct X private, then you will get an error if you try to pass a struct of type X by value

• Thus, as a designer of a struct, you can exercise great control over how the struct gets used

(40)

Classes

• A class is essentially the same as a struct, except:

– Any members/member functions in a struct are public by default

– Any members/member functions in a class are private by default

(41)

Classes

• Example: A Queue class:

class Queue{

int elements[N], nWaiting, front;

public:

Queue(){…}

bool remove(int &v){…}

bool insert(int v){…}

};

• The members - elements, nWaiting and front will be private.

(42)

Example (with class)

class V3{

double x,y,z;

V3(double v){

x = y = z = v;

}

double X(){

return x;

} };

class V3{

double x,y,z;

V3(double v);

double X();

};

//implementations V3::V3(double v){

x = y = z = v;

}

double V3::X(){

return x;

}

(43)

Example (with struct)

struct V3{

double x,y,z;

V3(double v){

x = y = z = v;

}

double X(){

return x;

} };

struct V3{

double x,y,z;

V3(double v);

double X();

};

//implementations V3::V3(double v){

x = y = z = v;

}

double V3::X(){

return x;

}

(44)

Concluding Remarks

• The notion of a packaged software component is important.

• Making data members private: hiding the implementation from the user

• Making some member functions public: providing an interface using which the object can be used

• Separation of the concerns of the developer and the user

• Idea similar to what we discussed in connection with ordinary functions

– The specification of the function must be clearly written down (analogous to interface)

– The user should not worry about how the function does its work (analogous to hiding data members)

(45)

Input Output Classes

• cin, cout : objects of class istream, ostream resp. predefined in C++

• <<, >> : operators defined for the objects of these classes

• ifstream: another class like istream

• You create an object of class ifstream and associate it with a file on your computer

• Now you can read from that file by invoking the >> operator!

• ofstream: a class like ostream, to be used for writing to files

• Must include header file <fstream> to uses ifstream and ofstream

(46)

Example of file i/o

#include <fstream>

#include <simplecpp>

int main(){

ifstream infile(“f1.txt”);

// constructor call.

// object infile is created and associated

// with f1.txt, which must be present in the current directory

ofstream outfile(“f2.txt”);

// constructor call. Object outfile is created and associated // with f2.txt, which will get created in the current directory

repeat(10){

int v;

infile >> v;

outfile << v;

}

// f1.txt must begin with 10 numbers. These will be read and // written to file f2.txt

(47)

“String theory”

• Iterative computations are demonstrated well on arrays

strings … the system manages the array space for us

• Can assign and append to strings

• Can read a position: cout << message[px]

• Can write a position: message[px] = ‘q’

• That’s all we need for now

(48)

Printing a string in reverse

string message;

getline(cin, message);

int mx = message.size()-1;

while (mx >= 0) {

cout << message[mx];

--mx;

}

• mx updated in a completely predictable way

• Ideal candidate to write as for loop

Character at position mx in

string

message

(49)

Finding needles in a haystack

• Given two strings, needles and haystack

• needles has no repeated characters

• haystack may repeat characters

• How many characters in needles appear in haystack at least once?

• needles = “bat”, haystack = “tabla” à 3

• needles = “tab”, haystack = “bottle” à 2

(50)

One needle in a haystack

• Subproblem: given one character ch and a string find if ch appears in string at least once

char ch; // suitably initialized

string haystack; // suitably initialized int ans = 0; // will change to 1 if found

for (int hx = 0; hx < haystack.size(); ++hx) { if (ch == haystack[hx]) {

++ans;

break; // quit on first match }

(51)

Many needles: nested loop

main() {

string needles, haystack;

getline(cin, needles); getline(cin, haystack);

int ans = 0;

for (int nx=0; nx < needles.size(); ++nx) { char ch = needles[nx];

for (int hx = 0; hx < haystack.size(); ++hx) { if (ch == haystack[hx]) {

++ans;

break; // quit on first match }

} // ends haystack loop } // ends needles loop

Generalize to work in case needles can also

have repeated characters

(52)

Duplicate needles

• needles = “bat”, haystack = “tabla” à 3

• needles = “tab”, haystack = “bottle” à 2

• needles = “bata”, haystack = “tabla” à 3

• Two approaches

– Dedup needles before executing earlier code (reducing to known problem)

– Dedup needles “on the fly” (inside the nx loop)

Exercise: If the input strings have n and h

characters, at most how much time does

(53)

Generalize to arbitrary lengths

• “Hello” < “Help” but “Hello” > “Hell”

• Scan both strings from the beginning

• If differing character found, same as before

• If a string ends, it is “less” than the other

int ans=0, ax=0, bx=0, an=as.size(), bn=bs.size();

for (; ans==0 && ax < an && bx < bn; ++ax, ++bx) { if ( (ans = as[ax] – bs[bx]) != 0) break;

}

if (ans == 0) { ans = an – bn;

}

This results in an arbitrary integer as the return value in case of unequal

input string lengths, but the sign of ans is what is important

(54)

break

while (true) {

ans += base/fac;

base *= x;

fac *= (++ix);

if (base/fac < epsilon) { break;

}

cout << (base/fac) << endl;

Terminates immediately

enclosing

while loop

References

Related documents

motivations, but must balance the multiple conflicting policies and regulations for both fossil fuels and renewables 87 ... In order to assess progress on just transition, we put

The Congo has ratified CITES and other international conventions relevant to shark conservation and management, notably the Convention on the Conservation of Migratory

1# Declare a class Number that contains two data member value1 and value2 of the type of integer, define constructor to give initial value, and perform addition

Bamber (1917) recorded a singje specimen with secondary sex characters of male, testis on the left side, ovo-testis on the right side, right and left oviducts and male ducts,

These gains in crop production are unprecedented which is why 5 million small farmers in India in 2008 elected to plant 7.6 million hectares of Bt cotton which

 In Gryllus bimaculatus, the solitary phase is distinguished by the dark colouration of the body and reduced wings but the gregarious phase can be identified by the

A number which can neither be expressed as a terminating decimal nor as a repeating decimal is called an irrational number, For

The point at which the section plane intersects an edge of the solid is called the point of intersection (POI)... A section view is created by passing an imaginary cutting