I got a class Matrix and a class Row. Matrix has as member variable a pointer to a pointer of an object from class Row. I overloaded the operator [] for Matrix and Row. But somehow the overloaded operator from Row is never getting called and I can't figure out why not.
Example Code:
matrix.h
class Row
{
int* value;
int size;
public:
int& operator[](int i)
{
assert(i >= 0 && i < size);
return value[i];
}
};
class Matrix
{
private:
Row **mat; // Pointer to "Row"-Vector
int nrows, ncols; // Row- and Columnnumber
public:
Row& Matrix::operator[](int i){
assert(i >= 0 && i < nrows);
return *mat[i];
}
Row** getMat() {
return mat;
}
// Constructor
Matrix(int rows, int cols, int value);
};
matrix.cpp
#include "matrix.h"
Matrix::Matrix(int rows, int cols, int value) : nrows(rows), ncols(cols){
mat = new Row*[rows];
for(int i = 0; i < rows; i++) {
mat[i] = new Row(ncols);
for(int j = 0; j < ncols; j++){
// the operator-overload of Row[] isn't getting called and I don't get why not
mat[i][j] = value;
}
}
}
int main(){
Matrix m = new Matrix(2, 2, 4);
return 0;
mat[i] gives you Row*, and you want to call Row::operator[], but pointer to Row is not dereferenced automatically. So you have to dereference it manually: (*mat[i])[j].
So I just figured it out myself.
I tried to call the []-operator from Matrix through mat[][], but since mat is a Row** Row& Matrix::operator[](int i) is never getting called.
Related
I'm just going to preface this with the fact that I'm new to C++ so it's quite possible there's just a stupid error here, but I can't find it.
I'm just trying to overload the increment operator in a friend function. Everything compiles perfectly and everything works if I explicitly call the postfix increment overload:
operator++(*test, 0);
Every element in the matrix is incremented and the program prints it out using cout perfectly. The problem is when I try to do the normal ++ increment test++; it appears as though something wrong happens with the test pointer to where when it tries to print the test object it doesn't print anything.
Any idea what's going on? I'm clueless. Here's the code I'm working with...
Compile & Run
g++ -o App App.cpp Matrix.cpp
./App
App.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
#define X 9
int main(int argc, char *argv[])
{
// Start the actual program here
Matrix* test = new Matrix(3,3);
// Row 1
test->setElement(0,0,1);
test->setElement(0,1,2);
test->setElement(0,2,3);
// Row 2
test->setElement(1,0,4);
test->setElement(1,1,5);
test->setElement(1,2,6);
// Row 3
test->setElement(2,0,7);
test->setElement(2,1,8);
test->setElement(2,2,9);
operator++(*test, 0);
//test++;
//++test;
// Print the Matrix object
cout << *test << endl;
}
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
using namespace std;
class Matrix {
friend ostream& operator<<(ostream&, const Matrix&);
friend Matrix& operator++(Matrix&); // prefix increment
friend Matrix& operator++(Matrix&, int); // postfix increment
private:
int rows;
int cols;
int** elements;
public:
// Constructors
Matrix(int);
Matrix(int,int);
Matrix(const Matrix&);
// Define setters
void setElement(int,int,int);
// Define getters
int getRowCount();
int getColCount();
int getElementAt(int,int);
void increment();
// Destructor
~Matrix();
};
#endif
Matrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
//===================================
// DEFINE [CON]/[DE]STRUCTORS
//===================================
// Constructor for creating square matricies
Matrix::Matrix(int _size) {
rows = _size;
cols = _size;
elements = new int*[_size];
for (int i = 0; i < _size; i++) {
elements[i] = new int[_size];
}
}
// Constructor for supporting non-square matricies
Matrix::Matrix(int _rows, int _cols) {
rows = _rows;
cols = _cols;
elements = new int*[_rows];
for (int i = 0; i < _rows; i++) {
elements[i] = new int[_cols];
}
}
// Copy constructor
Matrix::Matrix(const Matrix& mat1) {
Matrix(mat1.rows, mat1.cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
elements[i][j] = mat1.elements[i][j];
}
}
}
// Destructor
Matrix::~Matrix() {
for (int i = 0; i < rows; i++) {
delete[] elements[i];
}
delete[] elements;
}
//===================================
// DEFINE SETTER FUNCTIONS
//===================================
void Matrix::setElement(int row, int col, int newElement) {
if (row > rows-1 || row < 0)
throw "Row out of index";
if (col > cols-1 || col < 0)
throw "Column out of index";
elements[row][col] = newElement;
}
//===================================
// DEFINE GETTER FUNCTIONS
//===================================
int Matrix::getRowCount() { return rows; }
int Matrix::getColCount() { return cols; }
int Matrix::getElementAt(int row, int col) {
if (row > rows-1 || row < 0)
throw "Row out of index";
if (col > cols-1 || col < 0)
throw "Column out of index";
return elements[row][col];
}
//===================================
// OVERRIDE OPERATOR FUNCTIONS
//===================================
// Print the Matrix to the output stream
ostream& operator<<(ostream& out, const Matrix& mat) {
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
out << mat.elements[i][j] << " ";
}
out << endl;
}
return out;
}
// Prefix. Increment immediately and return the object.
Matrix& operator++(Matrix& mat) {
cout << "Prefix ++ operator" << endl;
// Increment all elements in the object by 1
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
mat.elements[i][j] += 1;
}
}
return mat;
}
// Postfix. Return the current object and "save" the incremented.
Matrix& operator++(Matrix& mat, int x) {
cout << "Postfix ++ operator" << endl;
// Save the current values
Matrix* curVals = new Matrix(mat);
// Increment the object
++(mat);
// Return the unincremented values
return *curVals;
}
test++ increments the value of test, so that it will point to the memory after your Matrix object. You need to dereference the pointer to get a Matrix object, then apply the increment to that.
What you want is (*test)++ or ++*test.
I created a matrix class by using a vector< vector >
structure. When created, the matrix is filled with zeroes (probably not the best way to do it, I'm planning to change it).
The header of the class goes something like this:
class Matrix{
public:
/*Basic constructor, accepts matrix dimensions
Matrix(int nr, int nc);
/*return element i,j*/
double elem(int i, int j);
/*operator () overloading - same thing as previous method*/
double operator()(int i, int j);
private:
vector<vector<double> > Matrix_;
int nr_, nc_;
};
while the implementation is:
//CONSTRUCTOR
Matrix::Matrix(int nrows, int ncols)
{
nc_ = ncols;
nr_ = nrows;
/*creates rows*/
for (int i = 0; i < nrows; i++)
{
vector<double> row;
Matrix_.push_back(row);
}
/*Fills matrix with zeroes*/
for (int i = 0; i < nr_; i++)
{
for (int j = 0; j < nc_; j++)
{
Matrix_[i].push_back(0);
}
}
}
/*method returning i,j element of the matrix (I overloaded () to do the same)*/
double Matrix::elem(int i, int j)
{
return Matrix_[i][j];
}
/*operator () overloading*/
double Matrix::operator()(int i, int j)
{
return Matrix_[i][j];
}
Finally, in the main program I have:
Matrix m1(rows, cols);
for (int i=0; i<rows; i++)
{
for (int j=0; j<cols; j++)
{
m1(i,j) = i*j;
/*OR, using the other method*/
m1.elem(i,j) = i*j;
}
}
and the problem is that I am always returned the error:
matrix.cpp:55:27: error: lvalue required as left operand of assignment
m1.elem(i,j) = i*j;
no matter if I am using the method .elem() or the operator ().
So, I guess the problem is that I am not accessing the elements the proper way to change their values, but I don't understand why.
Any suggestion would be greatly appreciated, thanks!
In order to be able to modify a matrix element you need to return a reference to it:
double& Matrix::elem(int i, int j) {
return Matrix_[i][j];
}
and:
double& Matrix::operator()(int i, int j) {
return Matrix_[i][j];
}
You can also add these for const matrices:
double Matrix::elem(int i, int j) const {
return Matrix_[i][j];
}
and:
double Matrix::operator()(int i, int j) const {
return Matrix_[i][j];
}
im working with simple 2D array,but in my copy constructor i encounter a problem.
Here's a excerpt from my code:
//default constructor
Matrix::Matrix(int r, int c)
{
rows = r;
cols = c;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
//at member
int& Matrix::at(int i, int j)
{
return array[i][j];
}
//copy constructor
Matrix::Matrix(const Matrix & obj)
{
rows = obj.rows;
cols = obj.cols;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
for (int i = 0; i < obj.rows; i++)
{
for (int j = 0; j < obj.cols; j++)
at(i, j) =obj.at(i,j);//PROBLEM
}
}
when im trying to assign at(i,j)=obj.at(i,j) i get this:
the object has type qualifiers that are not compatible with the member function
as far as i know, copy constructor is supposed to be passed by (const class& obj).
what should i do?
That's because your copy constructor take a const parameter, and your method Matrix::at is not const.
I suggest you to do two versions of your at method, one const and one not :
// Use for assignement
int& Matrix::at(int i, int j)
{
return array[i][j];
}
// Use for reading
int Matrix::at(int i, int j) const
{
return array[i][j];
}
Your compiler should know in which case call which one without your help, depending if you are trying to modify or just read your instance :
Matrix matrix(4, 4);
matrix.at(1, 2) = 42; // Assignement method called
int i = matrix.at(1, 2); // Read method called
Realize two versions of at function, one const and one non-const.
int& Matrix::at(int i, int j)
{
return array[i][j];
}
int Matrix::at(int i, int j) const
{
return array[i][j];
}
I created a class called Matrix with a 2D array. I can run it with the constructor, copy constructor and destructor. When I introduce the unary negation operator, I get a run time error.
https://gist.github.com/anonymous/7823794
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
Matrix(int rSize=3, int cSize=3);
Matrix(const Matrix& m);
~Matrix();
bool setValue(int rSize, int cSize, int value);
bool getValue(int rVal, int cVal, int& value)const;
const Matrix operator- ();
private:
int rowSize;
int columnSize;
int** arr;
};
#endif
#include<iostream>
#include"Matrix.h"
using namespace std;
Matrix::Matrix(int rSize,int cSize)
{
columnSize = cSize;
rowSize = rSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
arr[i] = new int[columnSize];
for(int j=0; j<rowSize; j++)
{
for(int k=0; k<columnSize; k++)
arr[j][k] = 0;
}
}
Matrix::Matrix(const Matrix& m)
{
columnSize = m.columnSize;
rowSize = m.rowSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
{
arr[i] = new int [columnSize];
}
for(int i=0; i<rowSize; i++)
{
for(int j=0; j<columnSize; j++)
arr[i][j] = m.arr[i][j];
}
}
Matrix::~Matrix()
{
for(int i = 0; i < rowSize; ++i)
delete [] arr[i];
delete [] arr;
}
bool Matrix::setValue(int rVal, int cVal, int value)
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
arr[rVal][cVal] = value;
return true;
}
bool Matrix::getValue(int rVal, int cVal, int& value)const
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
value = arr[rVal][cVal];
return true;
}
const Matrix Matrix:: operator- ()
{
Matrix m(*this);
for (int i = 0; i< rowSize; i++)
{
for(int j=0; j<columnSize; j++)
m.arr[i][j] = (this->arr[i][j])* -1 ;
}
return m;
}
#include<iostream>
#include"Matrix.h"
using namespace std;
void main()
{
Matrix m(4, 5);
Matrix m2(m);
m2.setValue(1,2,12);
int x;
m2.getValue(1,2,x);
Matrix m3;
m3 = -m2;
}
Edit: Following #unwind and #interjay advice, I implemented the assignment operator first and returned a value, not a reference, for the negation operator and it works. Thank you all for your help
You don't have an assignment operator in your class, which will cause double deletion of the member pointer after an assignment (and you're assigning in the line m3 = -m2;).
You should obey the rule of three.
unwind is also correct that the negation operator should return by value: You should never return a reference to a local variable from a function as that leads to undefined behavior.
Declaring the operator to return const Matrix& and then returning a local variable is wrong. That's a dangling reference, surely?
See for reference this answer where the operator returns an actual new value, not a reference. This makes a lot more sense to me.
I got the following class:
class Matrix{
private:
int rows;
int columns;
double* matrix;
public:
Matrix();
explicit Matrix(int N);
Matrix(int M, int N);
void setValue(int M, int N, double value);
double getValue(int M, int N);
bool isValid() const;
int getRows();
int getColumns();
~Matrix();
friend ostream& operator<<(ostream &out, Matrix&matrix1);
Matrix &operator=(const Matrix &m) {
if (rows * columns != m.rows * m.columns){
delete [] this->matrix;
this->matrix = new double[m.rows * m.columns];
}
rows = m.rows;
columns = m.columns;
for(int i = 0; i < rows; i++){
for(int j = 0; j < columns; j++){
this->matrix[i * columns + j] = m.matrix[i * columns + j];
}
}
return *this;
}
Matrix(const Matrix &rhs);
};
with these functions
#include <iostream>
#include "Matrix.h"
using namespace std;
//OPPGAVE 2
Matrix::Matrix(){
matrix = NULL;
}
Matrix::Matrix(int N){
matrix = new double[N * N];
rows = N;
columns = N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(i==j)
matrix[i * N + j] = 1;
else
matrix[i * N + j] = 0;
}
}
}
Matrix::Matrix(int M, int N){
matrix = new double[M * N];
rows = M;
columns = N;
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++)
matrix[i * N + j] = 0;
}
}
Matrix::~Matrix(){
delete [] matrix;
}
void Matrix::setValue(int M, int N, double value){
matrix[M * columns + N] = value;
}
double Matrix::getValue(int M, int N){
return matrix[M * columns + N];
}
bool Matrix::isValid() const{
if(matrix==NULL)
return false;
else
return true;
}
int Matrix::getRows(){
return rows;
}
int Matrix::getColumns(){
return columns;
}
ostream& operator<<(ostream &out, Matrix&matrix1){
if(matrix1.isValid())
for(int i = 0; i < matrix1.getRows(); i++){
for(int j = 0; j < matrix1.getColumns(); j++)
out << matrix1.getValue(i,j) << "\t";
out << endl;
}
else
out << "Matrisen er ikke gyldig." << endl;
return out;
}
Matrix::Matrix(const Matrix &rhs) : rows(rhs.rows),
columns(rhs.columns),
matrix(new double[rows * columns]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
this->matrix[i * columns + j] = rhs.matrix[i * columns + j];
}
}
}
The exercise says:
a) Create a class Vector that inherits the MxN Matrix.
We want to use the Vector class as an interface to an Mx1 dimensional matrix with some
extra functionality.
b) Implement the following constructors for the Vector class.
• Vector()
Default constructor, should initialize the underlying matrix into the invalid state.
• explicit Vector(unsigned int N)
Should construct the underlying Mx1 Matrix, initialized as a zero-matrix. (The explicit keyword is not in the syllabus, but it should be used here.)
• Vector(const Matrix & other);
Copy-constructor from Matrix. Should assign a matrix to *this if and only if the matrix has dimensions Nx1, otherwise the resulting *this should be set to invalid. Hint: Reuse operator= from the Matrix-class.
This is what I've got so far:
#include "Matrix.h"
class Vector : public Matrix{
public:
Vector();
explicit Vector(int N);
Vector(const Matrix & other);
};
and
using namespace std;
#include <iostream>
#include "Vector.h"
Vector::Vector()
:Matrix(){ }
Vector::Vector(int N)
:Matrix(N,1){ }
How am I supposed to reuse the operator= from Matrix? If I try to copy it from the Matrix class into the Vector class, it says that rows, columns etc is inaccessible. How do I access these?
Is it possible to write a copy constructor for the Vector class more or less the same as the copy constructor for the Matrix class? They are both arrays, so I guess it should work?
Will the operators I overloaded for Matrix (not included here) automaticly be used if I multiply a Matrix with a Vector, or do I also need to include these somehow in the Vector class? (They were written outside the Matrix class in the Matrix.cpp-file.)
Next Im going to write set and get functions for the Vector class.
Is it possible to write these functions on this form?:
void Vector::setValue(int i, double value) {
Matrix::setValue(i, 1, value);
}
Help and tips are greatly appreciated!
What follows is hideous kludgery to satisfy an incompetent professor. Don't do this in the real world.
First, the misnamed "copy" constructor. If we weren't worried about the dimensions, we could do this (shudder):
Vector(const Matrix & other)
{
*this = other;
}
But we must check the dimensions first. We could do it this way:
Vector(const Matrix & other)
{
if(other.getColumns()==1)
*this = other;
}
But some chucklehead neglected to make getColumns() const, so this results in a compiler error. We could do something truly drastic, const cast:
Vector(const Matrix & other)
{
Matrix *p = const_cast<Matrix *>(&other);
if(p->getColumns()==1)
*this = other;
}
Or just something facepalmingly awful:
Vector(const Matrix & other)
{
Matrix M(other); // notice that this is not const
if(M.getColumns()==1)
*this = other;
}
Do you need help with the isValid stuff?
You are on the right track for the sets and gets. You can call operators with member function like syntax Class::operator*(args). Implementing the vector assignment would look something like this:
Vector & Vector::operator=(const Vector &v){
Matrix::operator=(v);
return *this;
}
You will want your Vector constructors to be declared public. I am thinking because you are using inheritance the compiler will generate correct copy constructors and assignment operators for the Vector class. You should write tests to verify this assumption.