Operator overloading

Started by
13 comments, last by rip-off 16 years, 2 months ago
I wasn't too sucessful in finding information on this topic... This is my class:
/**
  * matrix.h
  * Follow the white rabbit
  *
**/

class Matrix {
private:
    std::vector<std::vector<int> > matrix;
    int sizex;
    int sizey;
    int overvalue;

public:
    // Default constructor
    Matrix() {}

    // Fancy constructor, create a matrix full of 0
    Matrix( int width, int height, int max ) {
        sizex = width;
        sizey = height;
        overvalue = max + 1;

        std::vector<int> v( sizey, 0 );
        std::vector<std::vector<int> > vx( sizex, v );
        matrix = vx;
        // Future usage of matrix: matrix[x][y]
    }

    // Randomize the matrix
    void Randomize( int min, int max ) {
        for( int i = 0; i < sizey; i++ ) {
            for( int j = 0; j < sizex; j++ ) {
                matrix[j] = rand() %((max %overvalue) - min) + min;
            }
        }
    }

    void FlipSquareCW() {
        if( sizex == sizey ) {
            Matrix tmp( sizex, sizey, overvalue - 1 );
            tmp = matrix;

            for( int i = 0; i < sizey; i++ ) {
                for( int j = 0; j < sizex; j++ ) {
                    matrix[j] = tmp[(sizex - 1) - j]
                }
            }
        }
    }

    // Set a cell in the matrix
    void SetXYI( int x, int y, int i ) {
        matrix[x%sizex][y%sizey] = i %overvalue;
    }

    // Get the value of a cell in the matrix
    int GetXY( int x, int y ) {
        return matrix[x%sizex][y%sizey];
    }


};


/**
  * End of matrix.h
  *
**/

In the function FlipSquareCW(), I want to use = beteen two Matrix. How can I archieve this?
Advertisement
Quote:Original post by c4c0d3m0n
In the function FlipSquareCW(), I want to use = beteen two Matrix. How can I archieve this?


Nothing!

The compiler will automatically give you an operator= that works by directly assigning all of the member variables. In this case, I imagine that is what you want (in other cases it won't be). If you were to implement the default behaviour yourself, it would look like this:
Matrix operator=(Matrix lhs, Matrix rhs){  lhs.matrix = rhs.matrix;  lhs.sizex = rhs.sizex;  lhs.sizey = rhs.sizey;  lhs.overvalue = rhs.overvalue;  return lhs;}


You would also have to make this function a friend of the Matrix class. You could also write it as a member function, but I prefer the free function version.

HTH
That is my problem, my compiler doesn't automaticly do this. I get this compiler error:

matrix.h: In member function `void Matrix::FlipSquareCW()':
matrix.h:42: error: no match for 'operator=' in 'tmp = ((Matrix*)this)->Matrix::matrix'
matrix.h:7: note: candidates are: Matrix& Matrix::operator=(const Matrix&)
matrix.h:46: error: no match for 'operator[]' in 'tmp'
That is because "matrix" is of type std::vector< std::vector<int> >.

You would need "temp = *this;" or better "Matrix temp = *this;".

Also note that the vectors hold their size internally, you can find the size of a vector using std::vector<>::size(). For efficiency, most people would write a Matrix class that uses a single dimensional vector and treats it as a two dimensional array.

A simple formula to turn a x,y pair into a single dimensional index is:
int index = x + sizey * y;


It is also common to overload operator() to take two integer arguments and return a reference (a const and non const version) to make the interface a little friendlier:
class Matrix{    std::vector< std::vector< int > > matrix;public:    int &operator()( int x, int y )    {        return matrix[x][y];    }    const int &operator()( int x, int y ) const    {        return matrix[x][y];    }};void example( const Matrix &matrix ){    // ...    int i = matrix(x,y);}
matrix is a vector of a vector of ints. tmp is a Matrix. You can't convert from one to the other, only from the same type. I'm unsure of the best way to tell you what you want to do because I'm not really sure what you want to do. There is probably a better way, but for now I THINK what you want is to make tmp the same type as matrix like so:

vector<vector<int> > tmp

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

I realized my mistake soon after my post, thanks for the quick replay though. I am going to look into this operator overloading a little more. This is how my class looks now:

/**  * matrix.h  * Follow the white rabbit  ***/class Matrix {private:    std::vector<std::vector<int> > matrix;    int sizex;    int sizey;    int overvalue;public:    // Default constructor    Matrix() {}    // Fancy constructor, create a matrix full of 0    Matrix( int width, int height, int max ) {        sizex = width;        sizey = height;        overvalue = max + 1;        std::vector<int> v( sizey, 0 );        std::vector<std::vector<int> > vx( sizex, v );        matrix = vx;        // Future usage of matrix: matrix[x][y]    }    // Randomize the matrix    void Randomize( int min, int max ) {        for( int i = 0; i < sizey; i++ ) {            for( int j = 0; j < sizex; j++ ) {                matrix[j] = rand() %((max %overvalue) - min) + min;            }        }    }    void FlipSquareCW() {        if( sizex == sizey ) {            Matrix tmp( sizex, sizey, overvalue - 1 );            for( int i = 0; i < sizey; i++ ) {                for( int j = 0; j < sizex; j++ ) {                    tmp.SetXYI( j, i, matrix[j] );                }            }            for( int i = 0; i < sizey; i++ ) {                for( int j = 0; j < sizex; j++ ) {                    matrix[j] = tmp.GetXY( i, sizex - 1 - j );                }            }        }    }    // Set a cell in the matrix    void SetXYI( int x, int y, int i ) {        matrix[x%sizex][y%sizey] = i %overvalue;    }    // Get the value of a cell in the matrix    int GetXY( int x, int y ) {        return matrix[x%sizex][y%sizey];    }};/**  * End of matrix.h  ***/
Your constructor can be written as:
Matrix(int width, int height, int max) :    sizex(width),    sizey(height),    overvalue(max + 1),    matrix(sizex, std::vector<int>(sizey, 0)){}
However, I'd recommend taking the advice offered previously and storing the data in a single 1-d array.

I'm also curious what the 'overflow' value is for, and what the overall purpose of the matrix class is (so far, except for the overflow stuff, it looks like you could just as easily use boost::multi_array...).
Wow, that's neat! I shall rewrite all my constructors like that.

I don't quite see how that 1-d array would work, but it's late, and I'm probably just too deaf to see it.

The overflow value is to keep stuff in bounds. I don't even know why I put it there anymore. I use it instead of a maximum var, because it's easier to use modulo like this.

This Matrix has several uses. One use is to hold the Tetris-field (a 10*20 array of the values 0-8) Another use is to hold the Tetrominoes (a 4*4 array of 0-1). The Tetrominoe array is a bool-array pretty much, that just holds the form. The type of block (the colour) is defined elsewhere.

I don't know much about boost, so I didn't think of using it.
rip-off gave an example earlier of how to index the 1-d array correctly (and also of how to overload operator()() for the purpose of accessing the matrix elements).

Really though, it seems like multi_array would be ideal for what you're describing (from what I've seen, the 'overflow' stuff in your matrix class doesn't look that useful).

Anyway, I'd check out some of the Boost libs if I were you; although implementing this sort of thing yourself can be a good learning experience, using proven third-party solutions is usually a win in terms of development time and quality of code.
Quote:Original post by c4c0d3m0n
Wow, that's neat! I shall rewrite all my constructors like that.


Argh, please don't re-write all of them :)
There are cases when you don't want initializer lists necessarily. The C++ FAQ Lite does a better job of explaining why you might not always want to use them.

~Shiny
------------'C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg.' -Bjarne Stroustrup

This topic is closed to new replies.

Advertisement