dcsimg


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 8 of 8

Thread: Operator Overloading Help

  1. #1
    Join Date
    Mar 2009
    Posts
    24

    Operator Overloading Help

    I have the following 2 classes:

    IntMatrix
    Code:
    class IntMatrix{
    private:
    	int x[3][4];
    };
    Matrix
    Code:
    IntMatrix m, n;
    	cout << "*** Printing if M == N" << endl;
    	cout << (m == n) << endl;
    	cout << "\n*** Printing M" << endl;
    	m.Print();
    	m[1][1] = 14;
    	cout << "\n*** Printing M - changed to 14" << endl;
    	m.Print();
    	m(2,17);  // replace all 2's with a 17
    	cout << "\n*** Printing M - changed 2 to 17" << endl;
    	m.Print();
    	cout << "\n*** Printing if M == N" << endl;
    	cout << (m == n) << endl;
    	IntMatrix p = m+n;
    	cout << "\n*** Printing P" << endl;
    	p.Print();
    }
    I need to create the public methods in IntMatrix that would make the following display on the screen:

    *** Printing if M == N
    1

    *** Printing M
    0 1 2 3
    1 2 3 4
    2 3 4 5

    *** Printing M - changed to 14
    0 1 2 3
    1 14 3 4
    2 3 4 5

    *** Printing M - changed 2 to 17
    0 1 17 3
    1 14 3 4
    2 3 4 5

    *** Printing if M == N
    0

    *** Printing P
    0 2 19 6
    2 16 6 8
    19 6 8 10

    How do I do this?

  2. #2
    Join Date
    Dec 2007
    Posts
    401
    > m(2,17); // replace all 2's with a 17
    for this, you need to overload the function call operator. this is a bad idea - it is unintuitive, and violates the principle of least surprise. prefer using a named operation like m.replace_all( 2, 17 ) ;

    > m[1][1] = 14;
    this is interesting because operator[] needs to be applied twice. you need to create and return a helper object (which encapsulates a single row of the matrix) for the first operator[] on which the second operator[] is applied.

    > m.Print();
    you could consider overloading operator<< (as a free function) instead.

    the rest of it is straightforward - overload operator==, != etc.

    Code:
    #include <cstddef>
    #include <cassert>
    #include <iostream>
    #include <iomanip>
    
    class IntMatrix
    {
      public:
        enum { ROWS = 3, COLS = 4 } ;
    
        class helper
        {
           public :
              int& operator[] ( std::size_t col )
              {
                 assert( col < COLS ) ;
                 return row[col] ;
              }
    
           private :
              explicit helper( int (&r)[COLS] ) : row(r) {}
              int (&row) [COLS] ;
    
              friend class IntMatrix ;
        } ;
    
        class const_helper
        {
           public :
              int operator[] ( std::size_t col )
              {
                 assert( col < COLS ) ;
                 return row[col] ;
              }
    
           private :
              explicit const_helper( const int (&r)[COLS] ) : row(r) {}
              const int (&row) [COLS] ;
    
              friend class IntMatrix ;
        } ;
    
        helper operator[] ( std::size_t row )
        {
            assert( row < ROWS ) ;
            return helper( x[row] ) ;
        }
    
        const_helper operator[] ( std::size_t row ) const
        {
            assert( row < ROWS ) ;
            return const_helper( x[row] ) ;
        }
    
        void operator() ( int old_value, int new_value )
        {
           for( std::size_t row = 0 ; row < ROWS ; ++row )
              for( std::size_t col = 0 ; col < COLS ; ++col )
                 if( x[row][col] == old_value ) x[row][col] = new_value ;
        }
    
        private: int x[ROWS][COLS] ;
    };
    
    template< typename OSTREAM >
    OSTREAM& operator<< ( OSTREAM& stm, const IntMatrix& m )
    {
       int w = stm.width() ;
    
       for( std::size_t row = 0 ; row < IntMatrix::ROWS ; ++row )
       {
          for( std::size_t col = 0 ; col < IntMatrix::COLS ; ++col )
                stm << std::setw(12) << m[row][col] ;
          stm << '\n' ;
       }
       stm << '\n' ;
    
       stm.width(w) ;
       return stm ;
    }
    
    int main()
    {
      IntMatrix m ;
      std::cout << m << '\n' ;
      m[1][2] = 9999 ;
      std::cout << m << '\n' ;
    }

  3. #3
    Join Date
    Mar 2009
    Posts
    24
    I've came up with the following so far:

    IntMatrix
    Code:
    ofstream outFile("out.txt", ios::app);
    
    IntMatrix::IntMatrix(){
    	int num = 0;
    	for(int i=0;i<3;i++)
            {
    		num = i;
                    for(int j=0;j<4;j++)
                    {
                            x[i][j] = num;
    			num++;
                    }
           }
    }
    
    bool IntMatrix::operator == (const IntMatrix & rhs){
    	bool same = true;
    	int i, j;
    	
    	for (i = 0; i < 3; i++)
    	{
    		for (j = 0; j < 4; j++){
    			if (rhs.x[i][j] == this->x[i][j])
    				return same;
    			else same = false;
                    }
    	}
    	return same;
    }
    
    void IntMatrix::Print(){
    	int i, j;
    	
    	for (i = 0; i < 3; i++)
    	{
    		for (j = 0; j < 4; j++)
    			outFile << this->x[i][j] << " ";
    		outFile << endl;
    	}
    }
    Matrix
    ofstream out("out.txt", ios::app);

    int main() {
    IntMatrix m, n;
    out << "*** Printing if M == N" << endl;
    out << (m == n) << endl;
    out << "\n*** Printing M" << endl;
    m.Print();
    }

    The following prints out:
    *** Printing if M == N
    1

    *** Printing M
    0 1 2 3
    1 2 3 4
    2 3 4 5

    I still am having trouble with the [][]. I'm not sure about Vijayan's code in regards to creating and returning a helper object.

  4. #4
    Join Date
    Dec 2007
    Posts
    401
    e[i][j] is equivalent to ( e[i] ) [j]
    one. first apply operator[] on e.
    two. then apply operator[] once again on on the object that step one returns.

    e[i][j] = 20 ; can be expanded to
    some_type temp = e[i] ; // e.operator[] (i) if e is of a user defined type
    temp[j] = 20 ;


    if you can afford to bypass range checking on the second subscript j, a helper object is not required; you could just return a (reference to) the array that forms row i.
    Code:
    #include <cstddef>
    #include <cassert>
    
    template< typename T = int, std::size_t ROWS = 3, std::size_t  COLS = 4 >
    class Matrix
    {
      public:
    
        typedef T row_type[COLS] ;
        typedef const T const_row_type[COLS] ;
    
        row_type& operator[] ( std::size_t row )
        {
            assert( row < ROWS ) ;
            return x[row] ;
        }
    
        const_row_type& operator[] ( std::size_t row ) const
        {
            assert( row < ROWS ) ;
            return x[row] ;
        }
    
        // ...
    
        private: T x[ROWS][COLS] ;
    };
    Last edited by vijayan; 05-08-2009 at 01:19 AM.

  5. #5
    Join Date
    Dec 2003
    Posts
    3,366
    Hopefully this is not too late, but if these are for a real matrix class, let me strongly recommend only using single dimensional storage. For example:

    double data[rows*cols];
    data[ 3*cols + 5] = 10; //same as (data[3][5] = 10)


    This opens up a lot of crazy matrix routines that create much difficulty in C++ using [][] notation. [][] is ok if everything is a square matrix of the same size, but once you get into reshapes, transposes, non-square multiply, partitioning, etc the [][] style forces you to allocate and copy data around many, many extra times while the single dimensional storage allows you to re-use the memory. consider: you have a 2X3 and transpose it to become a 3X2. They will both fit into double tbt[6] but only one of them will fit into double tbt[3][2].

  6. #6
    Join Date
    Mar 2009
    Posts
    24
    I have the following two classes:

    Code:
    class WordMatrix{
    private:
       char* x[5];
       int _ctr;
    Matrix
    Code:
    int Main(){
        {WordMatrix a;
        a.AddWord("hello");
        out << "\n*** Printing A" << endl;
        a.Print();
        }
        WordMatrix a;
        a.AddWord("today");
        a.AddWord("hello");
        out << "\n*** Printing A" << endl;
        a.Print();
        a = "world";
        out << "\n*** Printing A" << endl;
        a.Print();
        WordMatrix b = a;
        out << "\n*** Printing B" << endl;
        b.Print();
        out << "\n*** Adding Homework" << endl;
        a.AddWord("homework");
        a.Print();
        b.Print();
        out << "\n*** b[0] = a[3]" << endl;
        b[0] = a[3];
        a.Print();
        b.Print();
        WordMatrix c;
        c = b = a;
        out << "\n*** Printing A" << endl;
        a.Print();
        out << "\n*** Printing B" << endl;
        b.Print();
        out << "\n*** Printing C" << endl;
        c.Print();
        return 0;
    I need the AddWord(), Print(), operator[], and operator= methods that will print out the following:
    *** Printing A
    hello

    *** Printing A
    today hello

    *** Printing A
    today hello world

    *** Printing B
    today hello world

    *** Adding Homework
    today hello world homework
    today hello world

    *** b[0] = a[3]
    today hello world homework
    homework hello world

    *** Printing A
    today hello world homework

    *** Printing B
    today hello world homework

    *** Printing C
    today hello world homework

    Also please add any copy constructor, desctructor, or overloaded assignment operator if needed.

  7. #7
    Join Date
    Mar 2009
    Posts
    24
    If you like you could at least explain to me how to add, print, and copy an array of char pointers like char* x[5];.

  8. #8
    Join Date
    Dec 2003
    Posts
    3,366
    add is usually, but not always, "concatenate" (spelling?) which, for char arrays, can be done with the C function strcat if your strings always have a null termination. If not, you can do it by hand in a loop.

    print: cout and printf both work if your string is properly null terminated. If not print one char at a time instead, in a loop.

    copy: strcpy, memcpy, for loop, .... there are many ways to do this. Make sure you understand if you are copying a pointer (probably represents a whole row of data, or one string, depending on how you set it up) or a string, just make extra sure you know what the piece of data you are using actually *is*.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center