More About Classes. Gaddis Ch. 14, CS 2308 :: Fall 2015 Molly O'Neil

Similar documents
l A class in C++ is similar to a structure. - It allows you to define a new (composite) data type. l A class contains the following: - variables AND

Overloading Operators

! Data is stored in variables. - Perhaps using arrays and structs. ! Program is a collection of functions that perform

! Search: find a given target item in an array, ! Linear Search: Very simple search method: ! Operators such as =, +, <, and others can be

l A class in C++ is similar to a structure. - It allows you to define a new (composite) data type. l A class contains the following: - variables AND

! Data is stored in variables. - Perhaps using arrays and structs. ! Program is a collection of functions that perform

The Class. Classes and Objects. Example class: Time class declaration with functions defined inline. Using Time class in a driver.

! Data is stored in variables. - Perhaps using arrays and structs. ! Program is a collection of functions that perform

! Data is stored in variables. - Perhaps using arrays and structs. ! Program is a collection of functions that perform

! Data is stored in variables. - Perhaps using arrays and structs. ! Program is a collection of functions that perform

! A class in C++ is similar to a structure. ! A class contains members: - variables AND. - public: accessible outside the class.

! A class in C++ is similar to a structure. ! A class contains members: - variables AND. - public: accessible outside the class.

l A class in C++ is similar to a structure. l A class contains members: - variables AND - public: accessible outside the class.

l Operators such as =, +, <, can be defined to l The function names are operator followed by the l Otherwise they are like normal member functions:

! Operators such as =, +, <, can be defined to. ! The function names are operator followed by the. ! Otherwise they are like normal member functions:

Operator Overloading and Templates. Linear Search. Linear Search in C++ second attempt. Linear Search in C++ first attempt

14.1. Chapter 14: static member variable. Instance and Static Members 8/23/2014. Instance and Static Members

CSC1322 Object-Oriented Programming Concepts

Special Member Functions. Compiler-Generated Destructor. Compiler-Generated Default Constructor. Special Member Functions

Short Notes of CS201

CS201 - Introduction to Programming Glossary By

Chapter 9 Classes : A Deeper Look, Part 1

Special Member Functions

CPSC 427: Object-Oriented Programming

CS 376b Computer Vision

Fast Introduction to Object Oriented Programming and C++

III. Classes (Chap. 3)

Chapter 11: More About Classes and Object-Oriented Programming

And Even More and More C++ Fundamentals of Computer Science

Modern C++ for Computer Vision and Image Processing. Igor Bogoslavskyi

CSE 303: Concepts and Tools for Software Development

! Determine if a number is odd or even. ! Determine if a number/character is in a range. - 1 to 10 (inclusive) - between a and z (inclusive)

Inheritance and Polymorphism

! Determine if a number is odd or even. ! Determine if a number/character is in a range. ! Assign a category based on ranges (wind speed)

Lecture 7. Log into Linux New documents posted to course webpage

Lecture 5. Function Pointers

Copying Data. Contents. Steven J. Zeil. November 13, Destructors 2

CS32 - Week 1. Umut Oztok. June 24, Umut Oztok CS32 - Week 1

Discussion 1E. Jie(Jay) Wang Week 10 Dec.2

Chapter 10 Pointers and Dynamic Arrays. GEDB030 Computer Programming for Engineers Fall 2017 Euiseong Seo

Classes and Objects. Class scope: - private members are only accessible by the class methods.

CS24 Week 3 Lecture 1

Object-Oriented Programming

Function Overloading

CSE 374 Programming Concepts & Tools. Hal Perkins Fall 2015 Lecture 19 Introduction to C++

IS0020 Program Design and Software Tools Midterm, Fall, 2004

CSE 374 Programming Concepts & Tools. Hal Perkins Spring 2010

Object Oriented Programming. Assistant Lecture Omar Al Khayat 2 nd Year

KOM3191 Object Oriented Programming Dr Muharrem Mercimek OPERATOR OVERLOADING. KOM3191 Object-Oriented Programming

l Determine if a number is odd or even l Determine if a number/character is in a range - 1 to 10 (inclusive) - between a and z (inclusive)

Wentworth Institute of Technology COMP201 Computer Science II Spring 2015 Derbinsky. C++ Kitchen Sink. Lecture 14.

CS201- Introduction to Programming Current Quizzes

CS201 Some Important Definitions

Chapter 10. Pointers and Dynamic Arrays. Copyright 2016 Pearson, Inc. All rights reserved.

CPSC 427: Object-Oriented Programming

Introduction Of Classes ( OOPS )

Make Classes Useful Again

Part I: Short Answer (12 questions, 65 points total)

Object-Oriented Principles and Practice / C++

Homework 5. Yuji Shimojo CMSC 330. Instructor: Prof. Reginald Y. Haseltine

Distributed Real-Time Control Systems. Lecture 17 C++ Programming Intro to C++ Objects and Classes

(5 2) Introduction to Classes in C++ Instructor - Andrew S. O Fallon CptS 122 (February 7, 2018) Washington State University

Object-Oriented Programming for Scientific Computing

More class design with C++ Starting Savitch Chap. 11

C How to Program, 6/e by Pearson Education, Inc. All Rights Reserved. 1

Assignment of Structs

Pointers, Dynamic Data, and Reference Types

Computer Programming with C++ (21)

G52CPP C++ Programming Lecture 13

Chapter 13: Copy Control. Overview. Overview. Overview

Ch. 12: Operator Overloading

CSCI-1200 Data Structures Spring 2018 Lecture 8 Templated Classes & Vector Implementation

CSE 143. Linked Lists. Linked Lists. Manipulating Nodes (1) Creating Nodes. Manipulating Nodes (3) Manipulating Nodes (2) CSE 143 1

CMSC 202 Section 010x Spring Justin Martineau, Tuesday 11:30am

University of Illinois at Urbana-Champaign Department of Computer Science. First Examination

THE NAME OF THE CONSTRUCTOR AND DESTRUCTOR(HAVING (~) BEFORE ITS NAME) FUNCTION MUST BE SAME AS THE NAME OF THE CLASS IN WHICH THEY ARE DECLARED.

CS 11 C++ track: lecture 1

Programming, numerics and optimization

C++ Classes, Constructor & Object Oriented Programming

Agenda. The main body and cout. Fundamental data types. Declarations and definitions. Control structures

The University Of Michigan. EECS402 Lecture 15. Andrew M. Morgan. Savitch Ch. 8 Operator Overloading Returning By Constant Value

Pointers and Arrays CS 201. This slide set covers pointers and arrays in C++. You should read Chapter 8 from your Deitel & Deitel book.

SFU CMPT Topic: Classes

EL2310 Scientific Programming

CSCI-1200 Data Structures Fall 2018 Lecture 7 Templated Classes & Vector Implementation

Linked Lists. Gaddis Ch. 17. CS 2308 :: Spring 2016 Molly O'Neil

Object-Oriented Principles and Practice / C++

Copy Control 2008/04/08. Programming Research Laboratory Seoul National University

Object Oriented Programming COP3330 / CGS5409

University of Illinois at Urbana-Champaign Department of Computer Science. First Examination

Section Handout #4: Classes, Pointers, and Dynamic Memory

Software Engineering Concepts: Invariants Silently Written & Called Functions Simple Class Example

Chapter 8. Operator Overloading, Friends, and References. Copyright 2010 Pearson Addison-Wesley. All rights reserved

Object Oriented Programming in C#

Note 12/1/ Review of Inheritance Practice: Please write down 10 most important facts you know about inheritance...

Lecture 14: more class, C++ streams

Implementing an ADT with a Class

Object-Oriented Principles and Practice / C++

Object Oriented Design

Chapter 10 Introduction to Classes

Transcription:

More About Classes Gaddis Ch. 14, 13.3 CS 2308 :: Fall 2015 Molly O'Neil

Pointers to Objects Just like pointers to structures, we can define pointers to objects Time t1(12, 20, true); Time *tptr; tptr = &t1; We can access public members of the object using the structure pointer operator (->) Unlike structs, for objects, the public members are likely to be member functions, not variables tptr->addminute(); cout << tptr->tostring() << endl; Output: 12:21 AM 2

Dynamic Allocation of Objects Objects can be dynamically allocated with new Time *tptr = new Time(12, 20, true);... delete tptr; Passes arguments to the constructor Arrays of objects can also be dynamically allocated Time *tlist = new Time[100]; tlist[0].addminute();... Must use (and have) a default constructor! delete [] tlist; 3

Deleting Dynamically Allocated Objects Recall our MP3Player example from the OOP lecture: class MP3Player { private: Song *songs; int maxsongs; double maxmb; ; public: MP3Player(int, double); ~MP3Player(); double getmaxmb() const; MP3Player::MP3Player(int numsongs, double nummb) { songs = new Song[numSongs]; // dynamic allocation maxsongs = numsongs; maxmb = nummb; MP3Player::~MP3Player() { delete [] songs; 4

Deleting Dynamically Allocated Objects Where is the songs array deallocated? #include "MP3Player.h" int main() { MP3Player mp3(50, 25.0); #include "MP3Player.h" int main() { MP3Player *mp3; mp3 = new MP3Player(50, 25.0); cout << mp3.getmaxmb(); return 0; mp3.~mp3player() is called here, when mp3 goes out of scope. The destructor de-allocates mp3.songs, then mp3 is destroyed. cout << mp3->getmaxmb(); cout << endl; delete mp3; return 0; mp3->~mp3player() is called here, when mp3 is deleted. The destructor de-allocates mp3->songs, then mp3 is de-allocated. 5

The this Pointer this: A pre-defined pointer available within a class (inside the member function definitions) Always points to the instance (object) of the class whose function is being executed You can use this to access member variables that may be hidden by parameters with the same name: void Time::setHour(int hour) { if(hour < 1 hour > 12) this->hour = 0; else this->hour = hour; This means: Set the member variable called hour in THIS object to the value of the local variable called hour 6

Memberwise Assignment of Objects Can use the = operator to Assign (copy) one object to another Initialize an object with another object's data Just like = operator with structs, this will copy member variable to variable. For example: object2 = object1; means: copy all member values from object1 and assign the copied values to the corresponding member variables of object2 Member-wise assignment also used at initialization: Time t2 = t1; 7

Memberwise Assignment Demo Time t1(10, 20, true); Time t2(12, 40, false); cout << "t1: " << t1.tostring() << endl; cout << "t2: " << t2.tostring() << endl; cout << endl; t2 = t1; cout << "t1: " << t1.tostring() << endl; cout << "t2: " << t2.tostring() << endl; Output: t2 = t1; t1: 10:20 AM t2: 12:40 PM is equivalent to: t1: 10:20 AM t2: 10:20 AM t2.hour = t1.hour; t2.minute = t1.minute; t2.isam = t1.isam; 8

Copy Constructors Assignment and initialization use the same operator (=), but they are two different things: Object assignment calls the object's operator= function (more on this later...) Object initialization with the = operator calls the object's copy constructor A copy constructor is a specialized constructor called automatically when an object is initialized using an object of the same class Time t1; Time t2(t1); Time t3 = t1; Both call the copy constructor 9

Copy Constructors The copy constructor is also implicitly called when you pass an object as an argument to a function Just like other types, objects are passed by value in C++, i.e. copied into the function's local parameter variable As with default constructors and destructors, the compiler will provide a default copy constructor The default copy constructor performs memberwise assignment In many cases, this works just fine. However... 10

Uh-Oh... What if the object contains a pointer? class DynamicInt { private: int *val; // pointer to an int public: DynamicInt(int); ~DynamicInt(); ; int getval() const; void setval(int); 11

DynamicInt Implementation #include "DynamicInt.h" DynamicInt::DynamicInt(int v) { val = new int; *val = v; DynamicInt::~DynamicInt() { delete val; int DynamicInt::getVal() const { return *val; void DynamicInt::setVal(int v) { *val = v; 12

Uh-Oh... What happens if we try member-wise initialization of an object with a pointer to dynamically-allocated memory? DynamicInt i1(5); DynamicInt i2 = i1; i1.setval(10); cout << i1.getval() << endl; cout << i2.getval() << endl; What's the output? 10 5? 10 10 13

What Happened?! Pointer variables are storage locations that store addresses. In DynamicInt, the member variable that is copied on memberwise assignment is an int-pointer. The new object receives a copy of the address of the first object's allocation, not a new allocation There's still only one integer variable on the heap (dynamic memory), and both i1 and i2 have a pointer to it 10 i1 val i2 val This is called a shallow copy: Pointers are duplicated, but the locations they point at are not duplicated 14

Defining Your Own Copy Constructor Prototype of programmer-defined copy constructor (public member function): DynamicInt(const DynamicInt &); // goes in class declaration Definition of programmer-defined copy constructor: DynamicInt::DynamicInt(const DynamicInt &rhs) { val = new int; *val = rhs.getval(); // or *(rhs.val) // or even: setval(rhs.getval()); 15

Copy Constructor Parameter DynamicInt::DynamicInt(const DynamicInt &rhs) {... Why the reference parameter? Because if the parameter was pass-by-value, it would implicitly call the copy constructor to initialize the member function's parameter variable... which would call the copy constructor to initialize the parameter... which would call the copy constructor... oops! Why the const keyword? Because we're forced to pass by reference, without it we would be giving the copy constructor the ability to modify the argument object's member variables 16

Deep Copy Constructor A deep copy allocates new storage space for all dynamically-allocated member variables (pointers) and copies over the value, rather than just the pointer Assuming the programmer-defined copy constructor from 2 slides ago... DynamicInt i1(5); DynamicInt i2 = i1; // now calls OUR copy constructor i1.setval(10); cout << i1.getval() << endl; cout << i2.getval() << endl; 10 5 5 Output: i1 val i2 val 10 5 17

When Is Copy Constructor Called? Copy constructor is invoked... When we initialize an object from another object: DynamicInt i2 = i1; DynamicInt i3(i1); Implicitly by the compiler when we pass an object by value to a function parameter void somefunction(dynamicint obj); Implicitly by the compiler when we return an object by value from a function DynamicInt somefunction(int x); 18

What About Assignment? The copy constructor is NOT invoked when we assign one existing object to another existing object Time t1(10, 20, true); Time t2(12, 40, false); t2 = t1; This invokes the assignment operator (=) Once again, the compiler provides a default one for all classes The default implements a shallow (memberwise) copy Once again, classes that allocate memory have a problem... 19

Let's Draw a Picture... DynamicInt i1(3); DynamicInt i2(7); i2 = i1; i1.setval(1); i1 val 31 i2 val 7 Memory Leak! We have a similar problem as with a shallow copy constructor, but it's even worse, because now we have a memory leak, too! We need to overload the default behavior of the = operator 20

Operator Overloading Operators (.e.g, =, +, <,...) can be overloaded to work for objects of a programmer-defined class To overload an operator for a class, define a member function named operator followed by the operator symbol you want to overload: operator+ to define the + operator, operator= to define the = operator, etc. Just like a regular member function: Prototype goes in the class declaration Function definition goes in the implementation file 21

Operator Overloading Prototype in class declaration (public member function): void operator=(const DynamicInt &rhs); operator= is the function name The operator function is defined from the perspective of the object on the left hand side of the assignment statement The reference parameter, DynamicInt &rhs, is the right hand side object in the assignment statement For the statement: i1 = i2 Inside the operator= function definition, val refers to i1's val member variable rhs.val refers to i2's val member variable 22

Calling an Overloaded Operator The operator function is called on the object on the left hand side of the operator It can be called like a normal member function (if you really like writing strange-looking code...): DynamicInt i1(5); DynamicInt i2(10); i1.operator=(i2); It can also be called using the more conventional operator syntax: i1 = i2; Both call the same operator= member function, from the perspective of i1 23

Overloading = for DynamicInt class DynamicInt { private: int *val; // pointer to an int ; public: DynamicInt(int); // constructor DynamicInt(const DynamicInt &); // copy constructor ~DynamicInt(); // destructor int getval() const; void setval(int); void operator=(const DynamicInt &); void DynamicInt::operator=(const DynamicInt &rhs) { setval(rhs.getval()); DynamicInt i1(3); DynamicInt i2(7); i2 = i1; i1.setval(1); // i2's *val is now unchanged! 24

Overloading Other Operators The general reason you want to overload operators is to allow nicer syntax for common class operations For example, we may want to overload the - operator of our Time class to return the number of minutes between two times Overloading >> and << is another common use, to allow you to print out a class object or set its member variables from user input (but we won t do this in this class) However, there's nothing to stop you from doing weird and crazy things like turning the = operator into a printto-console operation, or making the * operator divide... You can overload almost all of the C++ operators, including ++, --, &&,, [], <<, etc. 25

Operators for Our Time Class (I've re-defined Time as a 12-hour clock with no AM/PM, to shorten the code) class Time { private: int hour; int minute; void addhour(); public: Time(); Time(int, int); int gethour() const; int getminute() const; void sethour(int); void setminute(int); int operator-(const Time &); bool operator==(const Time &); bool operator<(const Time &); Time operator+(const Time &); ; void addminute(); string tostring() const; 26

Time::operator- time1 - time2 is the number of minutes that separate the two times We can choose the return type: in this case, an integer int Time::operator-(const Time &rhs) { return (hour % 12) * 60 + minute - // 12 % 12 = 0 ((rhs.hour % 12) * 60 + rhs.minute); int main() { Time t1(12, 20); Time t2(4, 40); int minutesapart = t2 - t1; Output: 260 cout << minutesapart << endl; 27

Time::operator== & Time::operator< bool Time::operator==(const Time &rhs) { if(hour == rhs.hour && minute == rhs.minute) return true; return false; bool Time::operator<(const Time &rhs) { if(hour == rhs.hour) return (minute < rhs.minute); return (hour % 12) < (rhs.hour % 12); int main() { Time t1(12, 20); Time t2(12, 21); if(t1 < t2) cout << "correct" << endl; t1.addminute(); if(t1 == t2) cout << "correct again" << endl; Output: correct correct again 28

Time::operator+ time1 + time2 yields another time (e.g., 3:00 AM + 2:00 hours = 5:00 AM) Addition operator should return a new Time object Time Time::operator+(const Time &rhs) { int totalmin = (hour % 12) * 60 + minute + (rhs.hour % 12) * 60 + rhs.minute; int totalhours = totalmin / 60; // int div, rounds down totalhours %= 12; // must be between 0 and 11 if(totalhours == 0) totalhours = 12; // convert 0:XX to 12:XX totalmin %= 60; // get remainder minutes Time result(totalhours, totalmin); // create new Time obj return result; int main() { Time t1(12, 5); Time t2(2, 50); Time t3 = t1 + t2; cout << t3.tostring() << endl; Output: 2:55 29

When An Object Must Return Itself Sometimes, an object must return itself as the result of a binary operation, like assignment: v1 = v2 = v3; is equivalent to v1 = (v2 = v3); Associativity of = operator is right to left Value of (v2 = v3) is v2 (the left-hand operand) This means v1 = v2 = v3 is equivalent to v2 = v3; v1 = v2; To make v1 = v2 = v3 work correctly, the assignment operator must also return the postassignment value of the left-hand operand! 30

Returning *this We overloaded operator= for DynamicInt, but we had a void return type! class DynamicInt { private: int *val; // pointer to an int public: int getval() const; void setval(int); DynamicInt operator=(const DynamicInt &); ; DynamicInt DynamicInt::operator=(const DynamicInt &rhs) { setval(rhs.getval()); return *this; this is a pointer, so must de-reference it to return the DynamicInt object 31

Instance & Static Members Instance variable: a member variable in a class. Each object (instance) of the class has its own copy (i.e. separate storage space). Static variable: one variable (storage location) shared among all instances (objects) of a class Exist for the lifetime of the program (including before any objects of the class have been instantiated) Static member function: a member function that can be called as a standalone function (without reference to any specific object of the class) Can be called before any objects of the class exist Function can access only static member variables (Normal member functions can access static member variables, too) 32

Tree Class w/ Static Variable class Tree { private: static int treecount; // static member variable int numleaves; // instance variable ; public: Tree(int); int getnumleaves() const; int gettreecount() const; // Outside of class declaration int Tree::treeCount = 0; Tree::Tree(int leaves) { treecount++; numleaves = leaves; Must define the static member variable here (Note "static" keyword is not repeated!) int Tree::getNumLeaves() const { return numleaves; int Tree::getTreeCount() const { return treecount; Normal member function can access static var 33

Demo of Static Variable #include <iostream> #include "Tree.h" using namespace std; int main() { Tree oak(306); Tree elm(635); Tree pine(951); treecount var is static, but gettreecount() is not and must be accessed through an instance/object cout << "We have " << pine.gettreecount() << " trees" << " in our program." << endl; cout << "The pine tree has " << pine.getnumleaves() << " leaves." << endl; What's the output? What's the output if we replace pine.gettreecount() with elm.gettreecount()? 34

Instance vs. Static Variables There are 3 instances of the Tree class, but only one treecount variable treecount [static] 3 oak elm pine numleaves 306 numleaves 635 numleaves 951 35

Tree Class w/ Static Member Function class Tree { private: static int treecount; // static member variable int numleaves; // instance variable ; public: Tree(int); int getnumleaves() const; static int gettreecount(); No const keyword! // Outside of class declaration int Tree::getTreeCount() { return treecount; "static" keyword is not repeated here Static member functions cannot be declared const "const" means "doesn't modify the state of any instance variables"; static functions can't access instance variables! 36

Demo of Static Member Function #include <iostream> #include "Tree.h" using namespace std; We can now call gettreecount() independent of any object int main() { cout << "We have " << Tree::getTreeCount() << " trees" << " in our program." << endl; Tree oak(306); Tree elm(635); Tree pine(951); Can still access static function through an object, too... but this results in less intuitive code! cout << "Now we have " << pine.gettreecount() << " trees" << " in our program." << endl; cout << "The pine tree has " << pine.getnumleaves() << " leaves." << endl; 37