Matrices Introducing Inheritance. Consider A matrix is a grid in which numbers can be stored. Algorithms for problems in scientific computing frequently.

Slides:



Advertisements
Similar presentations
Operator overloading redefine the operations of operators
Advertisements

Exceptions, Templates, And The Standard Template Library (STL) Chapter 16.
Copyright © 2012 Pearson Education, Inc. Chapter 16: Exceptions, Templates, and the Standard Template Library (STL)
Class and Objects.
Chapter 14: Overloading and Templates
Operator Overloading in C++ Systems Programming. Systems Programming: Operator Overloading 22   Fundamentals of Operator Overloading   Restrictions.
Computer Science 1620 Multi-Dimensional Arrays. we used arrays to store a set of data of the same type e.g. store the assignment grades for a particular.
CS 117 Spring 2002 Classes Hanly: Chapter 6 Freidman-Koffman: Chapter 10, intro in Chapter 3.7.
Chapter 16 Templates. Copyright © 2006 Pearson Addison-Wesley. All rights reserved Learning Objectives  Function Templates  Syntax, defining 
Chapter 8 Arrays and Strings
C++ fundamentals.
Operator Overloading in C++
Data Structures Using C++1 Chapter 2 Object-Oriented Design (OOD) and C++
The switch Statement Selection Revisited. Problem Using OCD, design and implement a program that allows the user to perform an arbitrary temperature conversion.
C++ / G4MICE Course Session 3 Introduction to Classes Pointers and References Makefiles Standard Template Library.
Data Structures Using C++1 Chapter 2 Object-Oriented Design (OOD) and C++
More About Classes Chapter Instance And Static Members instance variable: a member variable in a class. Each object has its own copy. static variable:
1 Building Classes (the "++" in C++) (Chapter 14) Representing More Complex Objects.
Chapter 12: Adding Functionality to Your Classes.
Using Classes Chapter 5. C++ An Introduction to Computing, 3rd ed. 2 Objectives Further software development using OCD. Introduce basic features of classes.
Classes Representing Non-Trivial Objects. Problem Write a program that reads a temperature (either Fahrenheit or Celsius), and displays that same temperature.
Chapter 8 Arrays and Strings
Case Study - Fractions Timothy Budd Oregon State University.
Vectors of Vectors Representing Objects with Two Dimensions.
Controlling Function Behavior Sequence, Selection and Repetition.
File I/O ifstreams and ofstreams Sections 11.1 &
File I/O ifstreams and ofstreams. Some istream Operations istream function Description cin >> ch; Extract next non-whitespace character from cin and store.
DATA STRUCTURES LAB 1 TA: Nouf Al-harbi
Parameter Passing Mechanisms Reference Parameters Read § §
C++ An Introduction to Computing, 3rd ed. 1 Repetition Chapter 7.
1 Simple Functions Writing Reuseable Formulas. In Math Suppose f (x) = 2 x 2 +5Suppose f (x) = 2 x 2 +5 f(5)=?f(5)=? f(5) = 2* =55f(5) = 2*
Parameter Passing Mechanisms Reference Parameters § §
Overloading Operator MySting Example. Operator Overloading 1+2 Matrix M 1 + M 2 Using traditional operators with user-defined objects More convenient.
CPSC 252 Operator Overloading and Convert Constructors Page 1 Operator overloading We would like to assign an element to a vector or retrieve an element.
File I/O 1 ifstreams and ofstreams Sections 11.1 & 11.2.
Classes Representing Non-Trivial Objects. Problem Write a program that reads a temperature (either Fahrenheit or Celsius), and displays that same temperature.
Class Miscellanea Details About Classes. Review We’ve seen that a class has two sections: class Temperature { public: //... public members private: //...
Practice Building Classes Modeling Objects. Problem Write a program that computes the Dean’s List (full-time students whose GPA 3.0), using a student.
Vectors One-Dimensional Containers. Problem A file contains a sequence of names and scores: Ann92 Bob84 Chris89... Using OCD, design and implement a program.
C++ Programming: From Problem Analysis to Program Design, Third Edition Chapter 15: Overloading and Templates.
Copyright © 2009 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 14: More About Classes.
 2008 Pearson Education, Inc. All rights reserved. 1 Arrays and Vectors.
Simple Functions Writing Reuseable Formulas. Problem Using OCD, design and implement a program that computes the area and circumference of an Australian.
CHAPTER 2 PART #3 C++ INPUT / OUTPUT 1 st Semester King Saud University College of Applied studies and Community Service CSC1101 By: Fatimah.
CPS120: Introduction to Computer Science Lecture 16 Data Structures, OOP & Advanced Strings.
Learning Objectives Fundamentals of Operator Overloading. Restrictions of Operator Overloading. Global and member Operator. Overloading Stream-Insertion.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 26 Clicker Questions December 3, 2009.
Copyright © 2015, 2012, 2009 Pearson Education, Inc., Publishing as Addison-Wesley All rights reserved. Chapter 14: More About Classes.
Chapter 7 Constructors and Other Tools Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Chapter 16 Templates Copyright © 2008 Pearson Addison-Wesley. All rights reserved.
Friend Functions. Problem u Assuming two Complex objects u How would one add two numbers? W + X Complex operator+(const Complex& w, const Complex& x);
CPSC 252 ADTs and C++ Classes Page 1 Abstract data types (ADTs) An abstract data type is a user-defined data type that has: private data hidden inside.
1 C++ Classes & Object Oriented Programming Overview & Terminology.
Class Operations Creating New Types. Review Last time, we began building, a class to allow us to model temperatures: Last time, we began building Temperature,
Problem Session Working in pairs of two, solve the following problem...
Introduction to C++ (Extensions to C)
ifstreams and ofstreams
Vectors of Vectors Representing Objects with Two Dimensions.
Introducing Inheritance
Writing Reuseable Formulas
solve the following problem...
CMPE Data Structures and Algorithms in C++ February 22 Class Meeting
Introduction to Classes
Introduction to C++ Programming
Operator Overloading.
7 Arrays.
Vectors of Vectors Representing Objects with Two Dimensions.
Lab4 problems More about templates Some STL
ifstreams and ofstreams
Presentation transcript:

Matrices Introducing Inheritance

Consider A matrix is a grid in which numbers can be stored. Algorithms for problems in scientific computing frequently store the coefficients for a system of equations in a matrix, for convenient manipulation. A class to represent matrices is thus a useful class for scientific computing

Problem Let’s write a program to perform matrix addition  m1m2 m3 For simplicity, we will store a matrix’s values in a file. Since there is no predefined Matrix type, we will design a class... Since there is no predefined Matrix type, we will design a Matrix class...

Behavior Our program should explain its purpose, and prompt for and read the values of the first matrix from the keyboard. It should then do the same for the second matrix. It should then add the two matrices producing a third matrix. It should then display the third matrix to the screen.

Objects Description Type Kind Name 1st matrix Matrix varying matrix1 3rd matrix Matrix varying matrix3 screen ostream varying cout 2cd matrix Matrix varying matrix2 keyboard istream varying cin

Operations Description Predefined? Library? Name display a string yes string << read a matrix no --- >> from istream add 2 matrices no --- ??? write a matrix no --- ??? to ostream

Algorithm 0. Display purpose of program 1. Prompt for and read matrix1 using cin. 2. Prompt for and read matrix2 using cin. 3. Compute matrix3 = matrix1 + matrix2. 4. Write matrix3 to cout.

Coding Our Algorithm Ideally, we want to implement our algorithm this way: // matAdd.cpp //... documentation //... other #includes #include “Matrix.h” int main() { cout << “\nTo add two matrices, enter the” << “\n values of the first matrix“ << “\n (one row per line)\n”; Matrix mat1; cin >> mat1; cout << “\nDo the same for the second matrix:\n”; Matrix mat2; cin >> mat2; //...

Coding (Ct’d) //... matAdd.cpp continued Matrix mat3 = mat1 + mat2; cout << “\nThe sum of\n” << mat1 << “\n\n and\n\n” << mat2 << “\n\n is\n\n” << mat3 << “\n\n”; } If we build an easy-to-use Matrix class, writing a program to manipulate matrices can be as easy as writing a program that manipulates integers.

Analysis We have a few function members to define! Our algorithms requires: –matrix input from an istream –matrix addition –matrix output to an ostream In addition, we should provide “normal” class operations (normal constructors, accessors) as well as other Matrix operations.

Difficulty We could declare our Matrix class as follows: class Matrix { public: //... private: int myRows, myColumns; typedef vector Row; vector myGrid; }; However, if we do so, then we must redefine many of the vector operations for our Matrix class, which will greatly increase our development time.

For Example If we take this approach, then we will be unable to use the subscript operator on a Matrix object: Matrix mat1; //... cout << mat1[0][0] << endl; The reason is that a Matrix declared using this approach has-a vector of vectors as a data member, but such Matrix is not a vector of vectors. That is, although subscript is an operation defined for class vector, it is not defined for a Matrix unless we define it (as is the case for all vector operations).

A Solution One way to avoid this problem is to declare our Matrix class as an extension to vector of vectors: typedef vector Row; class Matrix : public vector { //... }; This approach tells the compiler that a Matrix is a. This approach tells the compiler that a Matrix is a vector >. Since such a Matrix is a, any operation that can be applied to can be applied to a Matrix (including subscript)! Since such a Matrix is a vector, any operation that can be applied to vector can be applied to a Matrix (including subscript)!

Example With this definition (and a constructor we’ll write shortly), we can write: Matrix mat1(2,3); inherited data member(s) [0] [1] [0][1][2] mat1 cin >> mat1[0][0];

Example With this definition (and a constructor we’ll write shortly), we can write: Matrix mat1(2,3); inherited data member(s) [0] [1] [0][1][2] mat1 cin >> mat1[0][0]; The first subscript selects the whose index is 0 within mat1. The first subscript selects the Row whose index is 0 within mat1.

Example With this definition (and a constructor we’ll write shortly), we can write: Matrix mat1(2,3); inherited data member(s) [0] [1] [0][1][2] mat1 cin >> mat1[0][0]; The first subscript selects the whose index is 0 within mat1. The first subscript selects the Row whose index is 0 within mat1. The second subscript selects the column whose index is 0 with in that. The second subscript selects the column whose index is 0 with in that Row.

Inheritance In such a declaration, Matrix is said to be derived from. In such a declaration, Matrix is said to be derived from vector. The Matrix class is said to inherit all of the members (data and function) of. The Matrix class is said to inherit all of the members (data and function) of vector. The pattern for such a declaration is as follows: class ChildClass : public ParentClass { //... }; ChildClass is derived from ParentClass, and inherits all of its members, both function and data.

Inheritance (Ct’d) The is-a relationship is often drawn like this: Parent Class Derived Class A parent class can have many derived classes, which are sometimes called child classes: Parent Class Child1Child2ChildN...

Inheritance (Ct’d) Child classes can also be parents, producing class hierarchies: Such hierarchies are useful for modeling relationships among real world objects. Parent Class Child1Child2ChildN... GChild1GChild2GChild3 Vehicle BoatCarTruck... compactwagon... sedan... By consolidating common code in parent classes, inheritance can eliminate all redundant code.

Using Inheritance Inheritance can be used to declare any class that is a special instance of another class. Since the derived class inherits all members of the parent class, inheritance should only be used if every operation on the parent class can be appropriately applied to the derived class

Declaring Matrix We can thus start a Matrix class as follows: typedef vector Row; class Matrix : public vector { public: private: int myRows, myColumns; }; No myGrid data member is needed, because Matrix inherits the implementation details of vector. The data members myRows and myColumns are not required, but they simplify some operations.

The Matrix Interface class Matrix : public vector { public: private: //... data members omitted }; Matrix(); Matrix(int rows, int columns); int Rows() const; int Columns() const; Matrix operator+(const Matrix & mat2) const; //... other Matrix-specific operations void Read(istream & in); void Print(ostream & out) const; friend istream & operator>>(istream & in, Matrix & chart); friend ostream & operator<<(ostream & in, const Matrix & chart);

Default Constructor The default constructor initializes the data members to default values: Matrix mat1; Specification: Postcondition: myRows == 0 && myColumns == 0. We should use the vector constructor to initialize the inherited data members...

Default Constructor inline Matrix::Matrix() : vector () { myRows = 0; myColumns = 0; } This is sufficiently simple to define inline in Student.h:

Default Constructor inline Matrix::Matrix() : vector () { myRows = 0; myColumns = 0; } This is sufficiently simple to define inline in Student.h: The notation calls the constructor for class (Matrix’s parent class). The notation : vector () calls the constructor for class vector (Matrix’s parent class). A derived class constructor can (and should) always use this pattern to call the constructor of its parent class, to initialize its inherited data members.

Explicit-Value Constructor Matrix mat1(3, 5); This constructor lets you construct a Matrix of a specified size (in rows and columns): Specification: Receive: rows, columns, two int values. Precondition: rows > 0 && columns > 0. Postcondition: myRows == rows && myColumns == columns && I contain a 2-D vector of rows rows and columns columns [0][1][2][3][4] [2] [1] [0] ??? mat1 myRows myColumns 3 5 The inherited data are wrapped in orange.

Explicit-Value Constructor inline Matrix:: Matrix(int rows, int columns) : vector (rows, Row(columns)) { assert(rows > 0 && columns > 0); myRows = rows; myColumns = columns; } This is sufficiently simple to define inline:

Explicit-Value Constructor inline Matrix:: Matrix(int rows, int columns) : vector (rows, Row(columns)) { assert(rows > 0 && columns > 0); myRows = rows; myColumns = columns; } This is sufficiently simple to define inline: The calls to initialize the inherited members. The : vector (rows, Row(columns)) calls vector () to initialize the inherited members. This constructor lets the caller specify the size (), and the initial value () of the vector. This constructor lets the caller specify the size ( rows ), and the initial value ( Row(columns) ) of the vector. The constructor (i.e., ) is used to define the initial value as a vector of size. The Row constructor (i.e., vector ) is used to define the initial value as a vector of size columns.

Extractors The extractors retrieve data member values: cout << mat1.Rows() << mat1.Columns(); Specifications: Rows():Return myRows. Rows():Return myRows. Columns():Return myColumns.

Extractors inline int Matrix::Rows() const { return myRows; } These are sufficiently simple to define inline: inline int Matrix::Columns() const { return myColumns; }

Element Access Thanks to our having derived Matrix from vector, we can write: cout << mat1[r][c]; and access the element at row, column, using the inherited subscript operators. and access the element at row r, column c, using the inherited subscript operators.

Element Access Thanks to our having derived Matrix from vector, we can write: cout << mat1[r][c]; and access the element at row r, column c, using the inherited subscript operators. Since mat1 is a vector, sending mat1 the subscript message [r] accesses the Row in mat1 whose index is r.

Element Access Thanks to our having derived Matrix from vector, we can write: cout << mat1[r][c]; and access the element at row r, column c, using the inherited subscript operators. Since is a vector, sending the subscript message [r] accesses the Row in whose index is r. Since mat1 is a vector, sending mat1 the subscript message [r] accesses the Row in mat1 whose index is r. We then send that Row the subscript message [c], which accesses the column within that Row whose index is c.

Print() mat1.Print(cout); This member lets you write a matrix to an ostream: Specification: Receive: out, an ostream. Output: my (Matrix) values, to out. Passback: out, containing my Matrix values;

Defining Print() //... void Matrix::Print(ostream & out) const { for (int r = 0; r < Rows(); r++) // for each r for (int c = 0; c < Columns(); c++) // for each c { fout << (*this)[r][c]; // display if (c < Columns()-1) // either out << ‘\t’; // tab else // or out << ‘\n’; // newline } This is sufficiently complicated to define separately.

this The tricky thing here is that within a function member, we must send ourselves the subscript message. Every C++ function member has a variable named. Every C++ function member has a variable named this. When that member’s message is sent to an object, the address of the receiving object is stored in. When that member’s message is sent to an object, the address of the receiving object is stored in this. mat1.Print(cin); Matrix::Print() this mat1

this (Ct’d) In a C++ function member, always contains the address of the object receiving the message. In a C++ function member, this always contains the address of the object receiving the message. Since it stores an address, can be thought of as pointing to the object receiving the message, and address-storing variables are commonly called pointers. Since it stores an address, this can be thought of as pointing to the object receiving the message, and address-storing variables are commonly called pointers. Since the value of is an address, we can’t use it as is to refer to the receiver of the message. Since the value of this is an address, we can’t use it as is to refer to the receiver of the message.

this (Ct’d) When applied to a pointer as a prefix operator, the asterisk () produces as its value the object pointed to. When applied to a pointer as a prefix operator, the asterisk ( * ) produces as its value the object pointed to. That is, if we use the notation: (*this) within a function member, the effect will be to access the receiver of the message (i.e., ourselves). To send ourselves the subscript message, we thus write: (*this)[r][c] which selects the whose index is within ourselves (and then sends that a second subscript message). which selects the Row whose index is r within ourselves (and then sends that Row a second subscript message).

Insertion cout << mat << endl; Overloading the insertion operator will let us display a Matrix in the “normal” manner: Since its left operand is an ostream, this function cannot be implemented as a function member. Specification: Receive: out, an ostream; mat, a Matrix. Output: the values in mat, via out. Passback: out, containing the Matrix. Return: out, for chaining.

Defining Insertion //... inline ostream & operator<<(ostream & out, const Matrix & mat) { mat.Print(out); // send mat the Print() msg return out; // allow chaining } Thanks to Print(), this is sufficiently simple to inline. We simply send our Matrix parameter the Print() message, and let it do the work...

Read() mat1.Read(cin); This member lets you read a matrix via an istream: Specification: Receive: in, an istream. Precondition: in contains the values of an m-by-n matrix, with each row on a separate line. Input: the matrix values, via in. Passback: in, the matrix values extracted from it. Postcondition: I contain the input values.

Defining Read() //... void Matrix::Read(istream & in) { double number; char separator; for (;;) // row-loop { Row aRow; // empty row for (;;) // column-loop { in >> number; // read number if (in.eof()) break; // quit if failed aRow.push_back(number); // append number in.get(separator); // read next char if (separator == ‘\n’) break;// quit if e-o-l } // end column-loop if (in.eof()) break; // quit if eof push_back(aRow); // append Row } // end row-loop } This is sufficiently complicated to define separately.

Extraction cin >> mat1; The extraction operator lets us read a Matrix from an istream, like any other object: Specification: Receive: in, an istream; mat, a Matrix. Precondition: myRows == m && myColumns == n && in contains the values of an m-by-n matrix, with one row/line. Input: the matrix, via in. Passback: in, the matrix read from it; mat, containing the extracted values. Return: in, for chaining.

Defining Extraction //... inline istream & operator>>(istream & in, Matrix & mat) { mat.Read(in); return in; } Thanks to Read(), this is simple enough to inline: We simply send our Matrix parameter the Read() message, and let it do the work...

Matrix Addition Matrix mat3 = mat1 + mat2; Defining the + operator will let us add matrices: Since its left operand is a Matrix, we can define operator+ as a Matrix function member, in which case such an expression will be treated as: Matrix mat3 = mat1.operator+(mat2);Specification: Receive: mat2, a Matrix. Precondition: mat2.Rows() == myRows && mat2.Columns() == myColumns. Return: mat3, containing the sum of myself and mat2.

Addition Operator //... Matrix Matrix::operator+(const Matrix & mat2) const { assert(mat2.Rows() == myRows && mat2.Columns() == myColumns); Matrix result(myRows, myColumns); for (int r = 0; r < myRows; r++) for (int c = 0; c < myColumns; c++) result[r][c] = (*this)[r][c] + mat2[r][c]; return result; } This is sufficiently complicated to define separately. Since the problem requires that we access all of the values in a 2-D structure, we use two nested for loops.

Our Program //... int main() { //... cin >> mat1; //... cin >> mat2; //... Matrix mat3 = mat1 + mat2; //... cout << mat3; //... } Our program will now work “as advertised”. All of our work is reuseable, and we can add more matrix-specific operations to class Matrix...

Summary If a new class is a special instance of an existing class, derivation can be used to define the new class. A derived class inherits all members (except constructors and destructors) of its parent class. A derived class constructor should use the parent class constructor to initialize inherited data members. In function members, is built-in variable containing the address of the receiver of the message. In function members, this is built-in variable containing the address of the receiver of the message. Within a function member, the expression refers to the object receiving the message. Within a function member, the expression (*this) refers to the object receiving the message.