When I try to use this line in main.cpp:
m3.array = m1.array+m2.array;
where m3, m1, and m2 are all objects of a class type Matrix, with an int[3][3] array -
I keep getting an error that deals with an incompatible assignment of type int[3][3] and int[3][3] to opperand '+'. I don't know the exact error, because I'm not at a computer to compile the program.
Here's the matrix.cpp I have:
#include <iostream>
#include <string>
#include "matrix.h"
using namespace std;
Matrix::Matrix()
{
m1.array = 0;
}
istream& opeator >>(istream& inp, Matrix& m1)
{
int i, j;
for (i = 0; i < 3;i++)
{
for (j=0; j < 3;j++)
{
inp >> m1.array[i][j];
}
}
return inp;
}
ostream& operator <<(istream& outp, Matrix& m1)
{
int i, j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
out<<m1.array[i][j]<<" "<<endl;
}
}
return outp;
}
Matrix operator + (const Matrix& m1, const Matrix& m2)
{
Matrix answer;
int i,j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
answer.array[i][j] = m1.array[i][j] + m2.array[i][j];
}
}
return answer;
}
Matrix operator - (const Matrix& m1, const Matrix& m2)
{
Matrix answer;
int i, j;
for (i = 0;i<3;i++)
{
for (j = 0;j<3;j++)
{
answer.array[i][j] = m1.array[i][j] - m2.array[i][j];
}
}
return answer;
}
Matrix operator * (const Matrix& m1, const matrix& m2)
{
Matrix answer;
int i, j, k;
for (i = 0;i<3;i++)
{
for (j = 0; j<3;j++)
{
for (k = 0; k<3;k++)
{
answer.array[i][j] = m1.array[i][k] + m2.array[k][j];
}
}
}
return answer;
}
and the matrix.h:
#ifndef MATRIX_H
#define MATRIX_H
using namespace std;
class Matrix
{
public:
Matrix();
friend istream& operator >>(istream&, Matrix&);
friend ostream& operator <<(ostream&, const Matrix&);
friend Matrix& operator +(const Matrix&, const Matrix&);
friend Matrix& operator -(const Matrix&, const Matrix&);
friend Matrix& operator *(const Matrix&, const Matrix&);
int array[3][3];
};
#endif
Matrix operator + (const Matrix& m1, const Matrix& m2)
This tells the computer how to add two Matrix objects, good job.
m3.array = m1.array+m2.array;
m1 and m2 are Matrix objects, but m1.array is not. That is a int[3][3] object. Luckily, the fix is very very simple:
m3 = m1 + m2;
The member array is of type int[3][3]. You are trying to add those two multi-dimensional arrays which has no meaning in C++.
I assume what you really want is:
m3 = m1 + m2;
which would call your overloaded operator.
Something else that is also suspicious is that your friend declarations and your actual definitions don't match up. The return types are different.
Related
I am a beginner in C++. I am learning on how to overload operators. I have created a class Complex that represents complex numbers and methods for complex arithmetic and a class ComplexArray that represents fixed-length arrays of elements in complex vector space C.
I get compiler errors, that it is unable to find the correct form of operator[]. However, I searched the internet and I am unable to rectify the error. Any hints/tips in the right direction would be of tremendous help.
Severity Code Description Project File Line Suppression State
Error C2676 binary '[': 'const ComplexArray' does not define this operator or a conversion to a type acceptable to the predefined operator ComplexArrays c:\users\quasa\source\repos\complexarrays\complexarrays\testcomplexarray.cpp 7
Here is my code:
TestComplexArray.cpp
#include <iostream>
#include "ComplexArray.h"
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < size; i++)
{
sum = sum + cArray[i];
}
return sum;
}
Complex ComplexProduct(const ComplexArray& cArray, int size)
{
Complex product = cArray[0];
for (int j = 1; j < size; j++)
{
product = product * cArray[j];
}
return product;
}
int main()
{
char ch;
const int size = 5;
ComplexArray cArray(size);
for (int i = 0; i < size; i++)
{
cArray[i] = Complex((double)(i + 1), 0);
std::cout << cArray[i];
}
Complex sum = ComplexSum(cArray, size);
Complex product = ComplexProduct(cArray, size);
std::cout << "Sum = " << sum << std::endl;
std::cout << "Product = " << product << std::endl;
std::cin >> ch;
return 0;
}
ComplexArray.h
class ComplexArray
{
private:
Complex* complexArr;
int size;
ComplexArray();
public:
//Constructors and destructors
ComplexArray(int size);
ComplexArray(const ComplexArray& source);
virtual ~ComplexArray();
//Range for the complexArr
int MaxIndex() const;
//Overload the indexing operator
const Complex& operator [](int index) const;
Complex& operator [](int index);
};
ComplexArray.cpp
#include "Complex.h"
#include "ComplexArray.h"
ComplexArray::ComplexArray(int s)
{
size = s;
complexArr = new Complex[size];
}
ComplexArray::ComplexArray(const ComplexArray& source)
{
//Deep copy source
size = source.size;
complexArr = new Complex[size];
for (int i = 0; i < size; i++)
{
complexArr[i] = source.complexArr[i];
}
}
ComplexArray::~ComplexArray()
{
delete[] complexArr;
}
int ComplexArray::MaxIndex() const
{
return (size - 1);
}
/*
c1.operator[](int index) should return a reference to the Complex
object, because there are two possible cases.
Case 1:
Complex c = complexArray[3];
Case 2:
complexArray[3] = c;
In the second case, complexArray[3] is an lvalue, so it must return
a Complex object by reference, so that it can be assigned to.
*/
const Complex& ComplexArray::operator[] (int index) const
{
return complexArr[index];
}
Complex& ComplexArray::operator[](int index)
{
return complexArr[index];
}
Complex.h
#include <iostream>
class Complex
{
private:
double x;
double y;
void init(double xs, double ys); //Private helper function
public:
//Constructors and destructors
Complex();
Complex(const Complex& z);
Complex(double xs, double ys);
virtual ~Complex();
//Selectors
double X() const;
double Y() const;
//Modifiers
void X(double xs);
void Y(double ys);
//Overload binary +, = and * operators
Complex operator + (const Complex& z);
Complex& operator = (const Complex& z);
Complex operator * (const Complex& z) const;
//Overload unary - operator
Complex operator -() const;
friend Complex operator * (const double alpha, const Complex& z);
friend Complex operator * (const Complex& z, const double beta);
//Overload << operator
friend std::ostream& operator << (std::ostream& os, const Complex& z);
//A complex function f(z)=z^2
Complex square();
};
As you have all pointed out - I was missing the forward definition of a #include.
Complex.cpp has the header
#include "Complex.h"
ComplexArray.h has the header
#include "Complex.h"
ComplexArray.cpp has the header
#include "ComplexArray.h"
TestComplexNumbers.cpp has the header
#include <iostream>
#include "ComplexArray.h"
My compile-time errors have been resolved.
I don't think the error comes from operator[], as you can see in the function:
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < cArray.MaxIndex(); i++)
{
sum = sum + cArray[i];
}
}
You don't return a result. That's fatal.
ComplexArray depends on Complex but order of includes doesn't look right
#include "ComplexArray.h"
#include "Complex.h"
You have to forward-declare Complex before ComplexArray
class Complex;
Code fails at \testcomplexarray.cpp line 7 which is
Complex sum = cArray[0];
It looks like you have problem with ctors of Complex. Be sure that you have NOT defined such:
Complex(Complex& v); // that's bad. it prevents to use copy constructor
If you need copy ctor for some inconceivable reason, it always should look so:
Complex(const Complex& v);
Everthing is in the code
Here is code. Constructor's.
Polynomial::Polynomial()
{
base=0;
Coefficients=new int [base+1];
Coefficients[0]=0;
}
Basically creates Poly equals to 0;
Polynomial::Polynomial(const unsigned int length,const int* table)
{
base=length;
bool a=false;
for(int i=length;i>=0;i--)
{
if(table[i]==1&&a==false)
{
a=true;
Coefficients=new int[base+1];
};
if(table[i]==0&&a==false)
{
base--;
};
if(a==true)
Coefficients[i]=table[i];
}
}
Here we create Poly with given length(it can be higher than Poly base)
I think so far everything is ok.
Now copy constructor:
Polynomial::Polynomial(const Polynomial& P)
{
base = P.base;
Coefficients=new int[base+1];
for(unsigned int i=0; i<base+1;i++)
{
Coefficients[i]=P.Coefficients[i];
}
}
And assign operator:
Polynomial& Polynomial::operator =(const Polynomial &P)
{
base=P.base;
for(unsigned int i=0;i<P.base+1;i++)
Coefficients[i]= P.Coefficients[i];
return *this;
}
I think there is smth wrong with this because when i overloaded + operator
And created Polynomial a,u,v;
When i typed a=v+u;
Sometimes i had garbage values and " Process returned -1073741819 (0xC0000005)"
I've read some about switch/copy but is there simple solution in my code that I am missing on?
Polynomial operator +(const Polynomial& a,const Polynomial& b)
{
Polynomial c;
if(a.base>=b.base)
c.base=a.base;
else
c.base=b.base;
c.Coefficients=new int[c.base+1];
for(unsigned int i=0;i<c.base+1;i++)
{
c.Coefficients[i]=0;
};
for(unsigned int i=0;i<b.base+1;i++)
{
c.Coefficients[i]=b.Coefficients[i];
};
for(unsigned int i=0;i<a.base+1;i++)
{
c.Coefficients[i]+=a.Coefficients[i];
}
return c;
}
Here is destructor
Polynomial::~Polynomial()
{
delete []Coefficients;
}
+= operator
Polynomial& Polynomial::operator +=(const Polynomial& a)
{
if(a.base>base)
{
base=a.base;
Coefficients = (int*)realloc(Coefficients, (base+1)*sizeof(int));
for(unsigned int i=0;i<base+1;i++)
{
if(Coefficients[i]!=0&&Coefficients[i]!=1)
{
Coefficients[i]=0;
}
Coefficients[i]+=a.Coefficients[i];
}
}
if(a.base<=base)
{
for(unsigned int i=0;i<a.base+1;i++)
{
Coefficients[i]+=a.Coefficients[i];
}
}
return *this;
}
So, I've looked around for an answer for a while, trying to solve this error. I think I know what the problem is, but I still can't find where or how it's happening exactly.
The error is that I'm getting a Access Violation at the location 0xcccccccc. My searching has lead me to that the problem is that I'm trying to delete a pointer that either doesn't exist, which I don't believe, or that I'm deleting a temporary variable. The problem is that I can't figure out which it is. I'm sure that once it's pointed out I'll feel stupid, but I REALLY can't seem to see this.
Pertinent Code down the callstack from the top.
// Minimum Polynomial Function
matrix matrix::MIN_POLY()
{
// Get stuff ready to find the Minimal Polynomial of the matrix
// Get our I matrix in.
col[0] = MatrixPow( *this, 0); // Goes in here <-
// ... Rest of the function ...
}
// Matrix Power Function
matrix matrix::MatrixPow(matrix& A, int pow)
{
// Create an identity matrix should the pow == 0
matrix ret(A.size[0], A.size[1]);
for(int i = 0; i < ret.size[0]; ++i)
{
ret.data[i][i] = 1;
}
for( int i = 0; i < pow; ++i)
{
// multiply it by the number of times given, and 0 returns I
ret = MatrixMult(ret, A);
}
// Ret.data exists here still and is ready to be moved and deleted.
return ret; // Seems to call Copy around here for some reason. <------
}
// Copy constructor
matrix::matrix(const matrix& other)
{
// Ret.data is gone by here for some reason.
if(data)
{
for(int i = 0; i < size[0]; ++i)
{
delete[] data[i]; // Error happens in one of these deletes <-----
}
delete[] data;
}
// Rest doesn't matter as it stops above
}
And the matrix.h since it was asked for.
#include <complex>
class matrix
{
private:
std::complex<float> **data; // [row][column]
int size[2]; // 0 is rows/ 1 is columns
public:
// Default Constructor
matrix();
// Default Destructor
~matrix();
// Default Copy
matrix(const matrix& other);
// Premade matrix constructor
matrix(int row, int col, std::complex<float>** mat);
// Assignment operator to get stuff done
matrix& operator=(const matrix& other);
// Set function for the matrix
void Set(int row, int col, std::complex<float> dat);
// Get function for the matrix, inline for ease.
std::complex<float> Get(int row, int col)
{return data[row][col];}
// Get function for the number of rows
int GetRows()
{return size[0];}
// Get function for the number of columns
int GetCol()
{return size[1];}
// Scalar Multiplication
void ScalarMult(std::complex<float> scalar);
// Matrix Multiplication
matrix MatrixMult(const matrix& A, const matrix& B);
// Matrix Power series
matrix MatrixPow(matrix& A, int pow);
// Matrix addition
matrix MatrixAdd(const matrix& lhs, const matrix& rhs);
// Row op addition
void RowOp(int row1, int row2, std::complex<float> val1, std::complex<float> val2);
// Row op Swap
void RowSwap(int row1, int row2);
// RREF function
void RREF();
// minimal Polynomial
matrix MIN_POLY();
};
You define copy constructor:
matrix::matrix(const matrix& other)
Do not initialize members:
matrix::matrix(const matrix& other)
{
//body...
}
And then perform such check:
if(data)
Which by all means cannot be false - all pointers all initialized to compiler-specific sentinel value to indicate uninitialized state and help detect bugs like this. This usually applies to debug builds, unless you enable this also in release builds.
Solution:
1. Initialize data:
matrix::matrix(const matrix& other)
: data(NULL)
{
//body...
}
2. Do not perform this unnecessary check:
matrix::matrix(const matrix& other)
: data(NULL)
{
// copy size
size[0] = other.size[0];
size[1] = other.size[1];
// Make the numbers match
data = new std::complex<float>*[size[0]];
for(int i = 0; i < size[0]; ++i)
{
data[i] = new std::complex<float>[size[1]];
for(int j = 0; j < size[1]; ++j)
{
data[i][j] = other.data[i][j];
}
}
return;
}
I'm working on an assignment for my C++ class and have run into a little problem when running the program. I get an error stating Unhandled exception at 0x000944C8 in Pog11.exe: 0xC0000005: Access violation writing location 0x00000000. while debugging. The goal is to read in the int degree of a polynomial, as well as the double coefficients.
here is the .h file that I was supplied:
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include<iostream>
using std::ostream;
using std::istream;
using std::cerr;
using std::endl;
class Polynomial
{
friend ostream& operator<<( ostream& left , const Polynomial& right);
friend istream& operator>>( istream& left , Polynomial& right );
public:
Polynomial();
Polynomial( int degree, const double* coefficients );
Polynomial( const Polynomial& );
~Polynomial();
const Polynomial& operator=( const Polynomial& deg);
bool operator==( const Polynomial& deg ) const;
void setDegree(int d);
int getDegree() const;
private:
int degree;
double* coefficients;
};
#endif
And here is the segment of code that is causing the error:
istream& operator>>(istream& left, Polynomial& right)
{
int tmp;
left >> tmp;
right.setDegree(tmp);
int i = 0;
while (i<=right.getDegree())
{
double co;
left >> co;
right.coefficients[i] = co;
i++;
}
return left;
}
Specifically the right.coefficients[i]=co; line is what causes the program to crash.
Here are the constructors for the class:
#include "Polynomial.h"
Polynomial::Polynomial() :degree(0), coefficients(0)
{
degree = 0;
coefficients = new double[degree];
}
Polynomial::Polynomial(int deg, const double* coefficients)
{
if (deg < 0)
{
degree = 0;
}
else
{
degree = deg;
}
coefficients = new double [degree];
}
Polynomial::Polynomial(const Polynomial& deg)
{
if (deg.getDegree() <= 0)
{
setDegree(0);
}
else
{
setDegree(deg.getDegree());
for (int i = 0; i < degree; i++)
{
coefficients[i] = deg.coefficients[i];
}
}
}
There's code missing - e.g. the implementation of the constructor of the Polynomial object.
I'm pretty sure that your error is that you have not allocated (enough) memory for the coefficients data member. There must be a
coefficients = new double[number_of_coeffs]
somewhere in your code.
EDIT
There's a number of points where you need to do this: where the degree of the polynomial is (re)set. Because then you know the degree of the polynomial:
Here you must copy the elements passed:
Polynomial( int degree, const double* coefficients ):
coefficients( new double[degree] ), degree( degree )
{
::memcpy(this->coefficients, coefficients, degree * sizeof(double));
}
and in this one, the degree of the polynomial changes - so your coefficients array must be modified accordingly.
Polynomial::setDegree( int degree ) {
// first delete the old coefficients
delete [] coeffs;
// and make a new array
this->degree = degree;
this->coefficients = new double[ this->degree ];
// initialize the coefficients
..
}
Similar actions have to be done in the copy constructor and the assignment operator.
Finally: you might be better off using std::vector<double> which basically does all the memory management for you. See http://en.cppreference.com/w/cpp/container/vector
#include<iostream>
using namespace std;
class term
{
public:
int exp;
int coeff;
};
class poly
{
public:
term* term_ptr;
int no_term;
poly(int d);
friend istream& operator>>(istream& in, poly& p);
friend ostream& operator<<(ostream& out, const poly& p);
friend poly operator+(const poly& p1, const poly& p2);
};
poly::poly(int d=0)
{
no_term = d;
term_ptr = new term[no_term];
}
istream& operator>>(istream& in, poly& p)
{
in>>p.no_term;
for(int i= 0; i<p.no_term; i++)
{
in>>(p.term_ptr+i)->coeff;
in>>(p.term_ptr+i)->exp;
}
return in;
}
i overloaded the input operator to input the object. The problem I am facing is when i input two objects consequtively the data member of the first object input changes.
int main(void)
{
poly p1, p2;
cin>>p1;
cin>>p2;
cout<<p1;
cout<<p2;
return 0;
}
if the input is
3
1 1
1 2
1 3
3
1 1
1 2
1 3
the output i get is
1 1
1 2
1 1
1 1
1 2
1 3
the output operator function is
ostream& operator<<(ostream& out, const poly& p)
{
out<<"coeff"<<" "<<"power"<<endl;
for(int i = 0; i< p.no_term; i++)
out<<(p.term_ptr+i)->coeff<<" "<<(p.term_ptr+i)->exp<<endl;
return out;
}
You initially allocate an array with zero elements. When reading the objects you read the number of terms but you don't reallocate the array of terms. I would personally recommend to use a suitable container type, e.g., std::vector<term*> or, actually, std::vector<std::shared_ptr<term>>. If you stick with arrays, you'd need something like this:
std::istream& operator>>(std::istream& in, poly& p)
{
if (in>>p.no_terms ) {
std::unique_ptr<term[]> terms(new term[p.no_terms]);
for(int i= 0; i<p.no_term; i++)
{
in >> terms[i].coeff;
in >> terms[i].exp;
}
if (in) {
delete[] p.term_ptr;
p.term_ptr = terms.release();
}
}
return in;
}
Change poly p1, p2; to poly p1(3), p2(3);.
p.no_term has a value of 3, however, look at your poly constructor:
poly::poly(int d=0)
{
no_term = d;
term_ptr = new term[no_term];
}
You are creating an array of 0 length. Also, no need to use pointer in your code. Here is an example using std::vector<term>:
#include<iostream>
#include <vector>
using namespace std;
class term
{
public:
int exp;
int coeff;
};
class poly
{
public:
std::vector<term> term_vec;
int no_term;
poly(int d);
friend istream& operator>>(istream& in, poly& p);
friend ostream& operator<<(ostream& out, const poly& p);
friend poly operator+(const poly& p1, const poly& p2);
};
poly::poly(int d=0) : term_vec(d), no_term(d)
{
}
istream& operator>>(istream& in, poly& p)
{
in>>p.no_term;
p.term_vec.resize(p.no_term);
for(int i= 0; i<p.no_term; i++)
{
in>> p.term_vec[i].coeff;
in>> p.term_vec[i].exp;
}
return in;
}
ostream& operator<<(ostream& out, const poly& p)
{
out<<"coeff"<<" "<<"power"<<endl;
for(int i = 0; i< p.no_term; i++)
out<<p.term_vec[i].coeff<<" "<<p.term_vec[i].exp<<endl;
return out;
}
int main(void)
{
poly p1, p2;
cin>>p1;
cin>>p2;
cout<<p1;
cout<<p2;
return 0;
}
Your default constructor argument d has value 0. Then you call new term[0]. Pointers that initialize as arrays with 0 length is pointed in same location in your example. After your fill non-valid memory and see same results.