1 / 28

Operator Overloading

ECE230 Lectures Series. Operator Overloading. Ying Wu Electrical & Computer Engineering Northwestern University yingwu@ece.northwestern.edu. Let’s program. Create a CMatrix class Data members? Get inputs? Print it out? Arithmetic operations?. 1 st version. class CMatrix {

alden
Download Presentation

Operator Overloading

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. ECE230 Lectures Series Operator Overloading Ying Wu Electrical & Computer Engineering Northwestern University yingwu@ece.northwestern.edu

  2. Let’s program • Create a CMatrix class • Data members? • Get inputs? • Print it out? • Arithmetic operations?

  3. 1st version class CMatrix { double *m_pData; int m_nNRow; int m_nNCol; public: CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor // getting and setting int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; // assignment const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); };

  4. CMatrix::CMatrix(int nrow, int ncol) { m_nNRow = nrow; m_nNCol = ncol; int size = m_nNRow*m_nNCol; m_pData = new double [size]; for(int i=0;i<size;i++) m_pData[i] = 0; } // copy constructor CMatrix::CMatrix(const CMatrix& m) : m_nNRow(m.m_nNRow), m_nNCol(m.m_nNCol) { int size = m_nNRow*m_nNCol; m_pData = new double [size]; for(int i=0;i<size;i++) m_pData[i] = m.m_pData[i]; } CMatrix::~CMatrix() { delete [] m_pData; }

  5. const CMatrix& CMatrix::operator=(const CMatrix& m) { int size = m_nNRow*m_nNCol; if(&m != this){ // check for self-assignment if(m_nNRow!=m.m_nNRow || m_nNCol!=m.m_nNCol){ delete [] m_pData; m_nNRow = m.m_nNRow; m_nNCol = m.m_nNCol; size = m_nNRow*m_nNCol; m_pData = new double [size]; } for(int i=0;i<size;i++) m_pData[i] = m.m_pData[i]; } return *this; } const CMatrix& CMatrix::operator=(const double& k) { if(m_nNRow!=1 || m_nNCol!=1){ delete [] m_pData; m_nNRow = 1; m_nNCol = 1; m_pData = new double; } m_pData[0] = k; return *this; }

  6. Use it! void main() { CMatrix a(3,4); cout << a.NRow() << a.NCol() << endl; CMatrix ttt = 10; // what does it mean? Make sure you understand it. CMatrix b; b = a; b = 2; // what does it mean? CMatrix c; c = 5; }

  7. What to add? • Overloading operators • Indexing? • Stream I/O? • Unary operations? • ++, -- • Binary operations? • == • != • +, -, *, • +=, -=, *=

  8. Operator overloading • Operator overloading • Enabling C++’s operators to work with class objects • Using traditional operators with user-defined objects • Requires great care; when overloading is misused, program difficult to understand • Examples of already overloaded operators • Operator << is both the stream-insertion operator and the bitwise left-shift operator • + and -, perform arithmetic on multiple types • Compiler generates the appropriate code based on the manner in which the operator is used

  9. Fundamentals • Overloading an operator • Write function definition as normal • Function name is keyword operator followed by the symbol for the operator being overloaded • operator+ used to overload the addition operator (+) • Using operators • To use an operator on a class object, it must be overloaded except the assignment operator(=)or the address operator(&) • Assignment operator by default performs memberwise assignment • Address operator (&) by default returns the address of an object

  10. Question? • I want a natural way to output a matrix i.e., CMatrix a(3,4); cout << a; • How can I do that?

  11. Overloading Stream-Insertion and Stream-Extraction Operators • Overloaded << and >> operators • Overloaded to perform input/output for user-defined types • Left operand of types ostream& and istream& • Must be a non-member function because left operand is not an object of the class • Must be a friend function to access private data members

  12. 2nd version: friend stream I/O class CMatrix { double *m_pData; int m_nNRow; int m_nNCol; public: friend ostream &operator<<( ostream &, const CMatrix &); CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor // getting and setting int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; // assignment const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); };

  13. // friend ostream ostream &operator<<( ostream &output, const CMatrix &m) { output.setf(ios::left, ios::adjustfield); output.precision(3); output << endl << "\t\t"; for(int r=0;r<m.m_nNRow;r++){ for(int c=0;c<m.m_nNCol;c++){ output << setw(8) << m(r,c); } if(r!=m.m_nNRow-1) output << endl << "\t\t"; } return output; }

  14. Operator Functions as Class Members vs. as friend Functions • Member vs non-member • Operator functions can be member or non-member functions • When overloading (), [], -> or any of the assignment operators, must use a member function • Operator functions as member functions • Leftmost operand must be an object (or reference to an object) of the class • If left operand of a different type, operator function must be a non-member function • Operator functions as non-member functions • Must be friends if needs to access private or protected members • Enable the operator to be commutative

  15. I want more … • I want to index the elements in a matrix i.e., CMatrix a(3,4); double t; t = a(1,1) + a(2,1); • How can I do that?

  16. 3rd version: indexing class CMatrix { double *m_pData; int m_nNRow; int m_nNCol; public: friend ostream &operator<<( ostream &, const CMatrix &); CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor // getting and setting int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; // assignment const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); // indexing double& operator()(int, int); const double& operator()(int, int) const; };

  17. // overloading indexing // reference return creates a lvalue (left value) double& CMatrix::operator()(int r, int c) { assert(r>=0 && r<m_nNRow); assert(c>=0 && c<m_nNCol); return m_pData[r*m_nNCol+c]; } // const reference return creates a rvalue (right value) const double& CMatrix::operator()(int r, int c) const { assert(r>=0 && r<m_nNRow); assert(c>=0 && c<m_nNCol); return m_pData[r*m_nNCol+c]; }

  18. I want to compare two matrices. • Compare two matrices? CMatrix a(3,4) CMatrix b(3,4) if( a==b){ cout << “they are equal” << endl; } else cout << “they are not equal” << endl; • How can I do that?

  19. 4th version: == and != class CMatrix { double *m_pData; int m_nNRow; int m_nNCol; public: friend ostream &operator<<( ostream &, const CMatrix &); CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); double& operator()(int, int); const double& operator()(int, int) const; // compare equal bool operator==(const CMatrix& m) const; bool operator==(const double& v) const; // not equal bool operator!=(const CMatrix &m) const { return !(*this==m); }; bool operator!=(const double& v) const { return !(*this==v); }; };

  20. bool CMatrix::operator==(const CMatrix &m) const { if(m_nNRow!=m.m_nNRow || m_nNCol!=m.m_nNCol) return false; int size = m_nNRow*m_nNCol; for(int i=0;i<size;i++){ if( m_pData[i] != m.m_pData[i]) return false; } return true; } bool CMatrix::operator==(const double& v) const { for(int i=0; i<Size(); i++){ if(m_pData[i] != v) return false; } return true; }

  21. I want a simple addition! • Wanna use CMatrix like a regular variable? CMatrix a(3,4); CMatrix b(3,4); CMatrix c(3,4); c = a+b; c = a+1; • How can I do that?

  22. 5th version: + class CMatrix { double *m_pData; int m_nNRow; int m_nNCol; public: friend ostream &operator<<( ostream &, const CMatrix &); CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); double& operator()(int, int); const double& operator()(int, int) const; bool operator==(const CMatrix& m) const; bool operator==(const double& v) const; bool operator!=(const CMatrix &m) const { return !(*this==m); }; bool operator!=(const double& v) const { return !(*this==v); }; CMatrix operator+(const CMatrix& m); CMatrix operator+(const double& t); };

  23. // overloading + CMatrix CMatrix::operator+(const CMatrix& m) { assert(m_nNRow == m.m_nNRow && m_nNCol == m.m_nNCol); CMatrix tmp(m_nNRow,m_nNCol); int size = m_nNRow*m_nNCol; for(int i=0;i<size;i++) tmp.m_pData[i] = m_pData[i] + m.m_pData[i]; return tmp; } CMatrix CMatrix::operator+(const double& t) { CMatrix tmp(m_nNRow,m_nNCol); int size = m_nNRow*m_nNCol; for(int i=0;i<size;i++) tmp.m_pData[i] = m_pData[i] + t; return tmp; }

  24. I want +=? • A step further? CMatrix a(3,4); CMatrix b(3,4); a += b; a += 2; • How can I do that?

  25. 6th version: += class CMatrix { double *m_pData; int m_nNRow, m_nNCol; public: friend ostream &operator<<( ostream &, const CMatrix &); CMatrix(int nrow = 1, int ncol = 1); // default constructor CMatrix(const CMatrix& m); // copy constructor ~CMatrix(); // destructor int NRow() const { return m_nNRow; }; int NCol() const { return m_nNCol; }; int Size() const { return m_nNRow*m_nNCol; }; const CMatrix& operator=(const CMatrix& m); const CMatrix& operator=(const double& k); double& operator()(int, int); const double& operator()(int, int) const; bool operator==(const CMatrix& m) const; bool operator==(const double& v) const; bool operator!=(const CMatrix &m) const { return !(*this==m); }; bool operator!=(const double& v) const { return !(*this==v); }; CMatrix operator+(const CMatrix& m); CMatrix operator+(const double& t); CMatrix& operator+=(const CMatrix& m); CMatrix& operator+=(const double& t); };

  26. // overloading += CMatrix& CMatrix::operator+=(const CMatrix& m) { assert(m_nNRow == m.m_nNRow && m_nNCol == m.m_nNCol); int size = m_nNRow*m_nNCol; for(int i=0;i<size;i++) m_pData[i] += m.m_pData[i]; return *this; } CMatrix& CMatrix::operator+=(const double& t) { int size = m_nNRow*m_nNCol; for(int i=0;i<size;i++) m_pData[i] += t; return *this; }

  27. Restrictions • C++ operators that can be overloaded • C++ Operators that cannot be overloaded

  28. Restrictions • Overloading restrictions • Precedence of an operator cannot be changed • Associativity of an operator cannot be changed • Arity (number of operands) cannot be changed • Unary operators remain unary, and binary operators remain binary • Operators &, *, + and - each have unary and binary versions • Unary and binary versions can be overloaded separately • No new operators can be created • Use only existing operators • No overloading operators for built-in types • Cannot change how two integers are added • Produces a syntax error

More Related