I have a problem with my program in c++. I try to write copy constructor. Everything is good until I start copying elements from array from object that is applied as a reference.
I can print every element of applied array but I can't copy it to array in object that copy constructor will create.
Here's the code (I show only the header file and some methods that needs copy constuctor because all code is too long I think)
Header.h
#pragma once
# include <iostream>
# include <fstream>
# include <cmath>
using namespace std;
class Polynomial {
private:
int degree;
double* coefficients;
public:
static const string errors[5];
Polynomial(const Polynomial& wzor); // konstruktor kopiujacy
Polynomial(float n);
~Polynomial();
void setCoefficient(unsigned int i, double value);
double getCoefficient(unsigned int i);
double value(double x);
friend ostream & operator <<(ostream & out, Polynomial & p);
double operator[](const int index);
double operator()(double x);
void operator=(Polynomial &obiekt);
friend Polynomial operator+(Polynomial &obiekt,Polynomial &obiekt1);
friend Polynomial operator-(Polynomial &obiekt,Polynomial &obiekt1);
friend Polynomial operator~(Polynomial &obiekt);
friend Polynomial operator*(Polynomial &obiekt,Polynomial &obiekt1);
friend Polynomial operator*(Polynomial &obiekt,double x);
};
Polynomial::Polynomial(float n) {
if(n<0){
throw 0;
}
else if(floor(n)-n != 0){
throw 2;
}
degree=(int)n;
coefficients=new double [(int)n+1];
for(unsigned int i=0; i<n; i++) {
coefficients[i]=0.0;
}
coefficients[(int)n]=1.0;
}
Polynomial::Polynomial(const Polynomial &wzor){
degree=wzor.degree; // it's allright
for(int i=0; i<=wzor.degree; i++){
coefficients[i]=wzor.coefficients[i]; // compilator says that this line is wrong
}
}
Polynomial::~Polynomial(){
delete coefficients;
}
Polynomial operator+(Polynomial &obiekt,Polynomial &obiekt1){
Polynomial nowy(1);
if(obiekt1.degree > obiekt.degree){
nowy=obiekt1;
for(int i=0; i<=obiekt.degree; i++){
nowy.coefficients[i]=nowy.coefficients[i]+obiekt.coefficients[i];
}
}
else{
nowy=obiekt;
for(int i=0; i<=obiekt1.degree; i++){
nowy.coefficients[i]=nowy.coefficients[i]+obiekt1.coefficients[i];
}
}
return nowy;
}
class Polynomial {
private:
int degree;
double* coefficients; // Pointer to double
/* ... */
}
You have declared coefficients to be a pointer to double, not an array.
for(int i = 0; i <= wzor.degree; i++) {
coefficients[i] = wzor.coefficients[i]; // Error! No memory allocated.
}
Here you are trying to assign values to memory that doesn't exist. You need to allocate the array before you can assign element data to it. Also you should initialize members in the initialization list instead of the ctor body. Try something like this instead:
Polynomial::Polynomial(const Polynomial& wzor)
: degree(wzor.degree), coefficients(new double[wzor.degree + 1]) { // Init
for (int i=0;i<=wzor.degree;i++) {
coefficients[i]=wzor.coefficients[i];
}
}
Remember that the copy constructor is a constructor. It will construct a new instance of the object and you need to allocate new memory for the new copy.
Also in your destructor you must use delete[] instead of delete as you are deleting an array.
The assignment operator should be declared as:
Polynomial& operator= (const Polynomial& obiekt);
You should use type std::size_t for variables storing array indexes instead of int.
Finally I recommend using containers from the standard library instead of built in arrays, e.g. std::vector.
#include <vector>
std::vector<double> coefficients;
you can use the copy of the vector which means you do not have to implement it on your own.
And you do not have to do the delete stuff.
Use resize & [] or push_back methods to work on the string. Your degree will be coefficients.size().
You're assignment operator is wrong. It should be
Polynomial & operator=(const Polynomial &obiekt);
Related
I built 2 classes, Multime (meaning set) and Array. I need to overload the * operator to do the intersection of sets and assign the result to another set. I decided to overload the = operator as well, to solve the latter. This is the header of Multime:
class Multime{
private:
Array a;
int* n;
public:
Multime();
Multime(Multime& ob);
~Multime();
void Transformare(Array t);//transforms an array into a set by eliminating duplicates
int& operator[] (int x);//makes ob[i] return ob.a[i];
Multime& operator+ (Multime& y);
Multime& operator=(Multime& y);
Multime& operator* (Multime& y);
void Afisare();//outputs the array in the object that called it
};
This is the header of Array:
class Array{
private:
int* c;///the array
int len, capacity;
public:
Array();
void Append(int);
~Array();
int& operator[] (int);//makes ob[i] retuen ob.c[i]
void Afisare();
void Sortare();//sorts the array
friend class Multime;
};
This is how I overload the = operator:
Multime& Multime::operator=(Multime& ob)
{
if(*n!=0) {
std::cout<<"don't overwrite a nonvoid set";
std::cout<<"the result should have been "<<ob.Afisare();
std::cout<<"n="<<*n;
}
else
{
if(this!=&ob)
{
for(int i=0; i<*ob.n; i++)
{
a.Append(ob.a[i]);
}
*n=*(ob.n);
}
}
return *this;
}
This is how I overload the * operator:
Multime& Multime::operator* (Multime& y)
{
Multime q;
for(int i=0; i<*n; i++)
{
for(int j=0; j<*y.n; j++)
{
if(a[i]==y.a[j])
q.a.Append(a[i]);
}
}
*q.n=q.a.len;
*this=q;
return *this;
}
If mul1 is the {1, 2, 3} set (with length 3, of course) and mul2 is {-2, 2, 5 9}, the code:
Multime mul5;
mul5=mul1*mul2;
outputs
don't overwrite a nonvoid set
the result should have been 2
n=3
I'm very confused as to why n is 3 although it was just created.
You get the output you do because of this line at the end of operator*:
*this=q;
You're overwriting the this parameter (which is mul1 from the caller), which is not an empty Multime object.
Fundamentally, your two operator* does not behave as a multiplication operator, because it modifies one of the parameters. Its behavior is that of an operator*= function. The signature for a member operator* would typically be something like
Multime Multime::operator*(const Multime& y) const
where it won't modify either parameter, and returns a new object. You can remove that problematic assignment from the end and just end it with return q;.
I'm trying to use + to add 2 vector (mathematical vector). Here's my code:
class Vector{
double v[Max_size];
int dim;
public:
int getDim() const;
Vector();
Vector(int n);
Vector(const Vector& a);
Vector add(const Vector&b);
friend Vector operator+(Vector summand1, Vector summand2);
};
Operator overloading:
Vector operator+(Vector summand1, Vector summand2){
int dim1 = summand1.getDim();
int dim2 = summand2.getDim();
assert(dim1 == dim2);
Vector sum(dim1);
int i;
for(i = 0; i < dim1; i++){
sum.v[i] = summand1.v[i] + summand2.v[i];
}
return sum;
}
And how I use it:
Vector m = v+t;
When I run the code, it always shows that m is (0,0) (2D vector), which is the default value generated by the constructor. What's wrong with it? Thanks!
Your copy constructor:
Vector::Vector(const Vector& a){
dim = a.dim;
Vector(dim);
}
correctly sets the value of the dim member, but has not other side effect.
You should have a variant of the following code:
Vector::Vector(const Vector& a) : dim(a.dim) {
std::copy(std::begin(a.v), std::end(a.v), v);
}
This will actually copy the data present in the parameter, and you will see the correct behavior for the code:
// Copy constructor called here, but did not correctly copy the data before.
Vector m = v + t;
For a better (by that I intend simpler and safer) Vector class, if you have access to a compiler that is at least C++11 compliant, you can write:
class Vector{
std::array<double, Max_size> v; // Note the std::array here.
int dim;
public:
int getDim() const;
Vector();
Vector(int n);
Vector(const Vector& a);
Vector add(const Vector&b);
friend Vector operator+(Vector summand1, Vector summand2);
};
The std::array will take care of everything, provided you write your copy constructor like this:
Vector::Vector(const Vector& a) : v(a.v), dim(a.dim) {
}
Or, even better, you could then let the compiler generate the copy constructor itself, with the same behavior.
For my own created Vector class:
class Vector
{
private:
double* elem;
int n;
public:
Vector();
Vector(const int s);
Vector(Vector&);
~Vector();
void print();
void set(const int, const double);
double get(const int) const;
int size() const;
double norm() const;
Vector add(const Vector&) const;
Vector subtract(const Vector&) const;
double scalar(const Vector&) const;
};
When I try to call the copy constructor:
Vector::Vector(Vector& x)
{
int count = 0;
n = x.n;
elem = new double[n];
while (count < n)
{
elem[n] = x.elem[n];
count++;
}
}
It copies the address instead of the elements of the vector. Does anybody have an idea why this happen?
P.S. I In the destructor I have written
delete []elem;
Because
Vector(Vector&);
it is not signature for a copy constructor. Right signature would be
Vector(const Vector&);
Compiler doesn't see user defined copy constructor and silently generates it's own default copy constructor which just make copy of
double* elem;
int n;
and doesn't care about allocation new memory and copying elements of array.
Vector::Vector(Vector& x)
{
int count = 0;
n = x.n;
elem = new double[n];
while (count < n)
{
elem[n] = x.elem[n];//here should be:elem[count] = x.elem[count]
count++;
}
}
I'm having trouble overloading the + operator, and I can't figure out what the cause is. The + operator returns a Polynomial (called C) but it returns it by value, where as the assignment operator is expecting a Polynomial object as a parameter passed by reference. To make C=A+B work, do I need to have a second assignment operator function that takes a Polynomial passed by value as an argument? Thanks!
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void line(int lines);
class Polynomial
{
private:
int degree;
int* coeffs;
public:
//constructors
Polynomial() {degree=0;coeffs=new int[1];}
Polynomial(int deg) {degree=deg;coeffs=new int[deg+1];}
Polynomial(const Polynomial& A);
//mutators
void GetCoeffs(istream& in);
void EditCoeff(int deg);
void ResetCoeffs();
int Coeff(int deg);
void Randomize(int max);
//accessors
void Show(ostream& out);
int Degree() {return degree;}
//operators
friend Polynomial operator+(Polynomial& A, Polynomial& B);
void operator =(Polynomial A);
};
int main()
{
Polynomial A(5);
Polynomial B(5);
A.Randomize(5);
B.Randomize(5);
A.Show(cout);
line(2);
B.Show(cout);
line(2);
Polynomial C(5);
C=A+B;
C.Show(cout);
return 0;
}
void Polynomial::Randomize(int max)
{
for (int i=degree; i>=0; i--)
{
coeffs[i]=rand()%(max+1) + 1;
if ((rand()%(101) + 1)%2 == 0)
coeffs[i]*=-1;
}
}
void Polynomial::operator =(Polynomial A)
{
if (degree==A.degree)
{
for (int i=degree; i>=0; i--)
{
coeffs[i]=A.coeffs[i];
}
}
}
Polynomial Polynomial::operator+(Polynomial& A, Polynomial& B)
{
Polynomial C;
if (A.degree>=B.degree)
{
C=A;
for (int i=B.degree; i>=0; i--)
{
C.coeffs[i]=A.coeffs[i]+B.coeffs[i];
}
C.Show(cout);
return C;
}
else
{
C=B;
for (int i=A.degree; i>=0; i--)
{
C.coeffs[i]=A.coeffs[i]+B.coeffs[i];
}
C.Show(cout);
return C;
}
}
int Polynomial::Coeff(int deg)
{
return coeffs[deg];
}
void line(int lines)
{
for (int i=0; i<lines; i++)
cout << endl;
}
void Polynomial::GetCoeffs(istream& in)
{
for (int i=degree; i>=0; i--)
{
in >> coeffs[i];
}
in.ignore();
}
void Polynomial::Show(ostream& out)
{
for (int i=degree; i>=0; i--)
{
if (coeffs[i]>=0)
{
if (i!=degree)
out << " + ";
out << coeffs[i];
}
else
{
if (coeffs[i]<0)
out << " - ";
out << 0-coeffs[i];
}
if (i>1)
out << "x^" << i;
else if (i==1)
out << "x";
}
}
Polynomial::Polynomial(const Polynomial& A)
{
coeffs=new int[A.degree+1];
degree=A.degree;
for (int i=A.degree; i>=0; i--)
{
coeffs[i]=A.coeffs[i];
}
}
This issue here is you have mixed up the global(Outside class definitions) operator+ and the member class definition of operator+.
(static) Polynomial operator+(Polynomial& A, Polynomial& B); This operator is used globally, so outside of a class.
Inside the class you need to use the following signature.
Polynomial& operator+(const Polynomial& other);
Here is an example.
Polynomial p;
Polynomial q;
p = p + q;
The code for this if the operator is define in the class is:
p = p.operator+(q); //only needs one parameter.
The code for this if the operator is define globally is:
p = ::operator+(p, q); //needs both parameter
NOTE:
To use it as a non member function remove Polynomial operator+(Polynomial& A, Polynomial& B); from your definition Polynomial Polynomial::operator+(Polynomial& A, Polynomial& B){/**/} should be move above the main function and it now becomes:
static Polynomial operator+(Polynomial& A, Polynomial& B){/**/}
Normally you would overload operator+ in one of two ways:
Polynomial operator+(const Polynomial &other) const;
or as a non-member function,
Polynomial operator+(Polynomial a, const Polynomial &b);
You don't normally need the friend qualifier for the latter since the implementation will likely be in terms of another overloaded operator already defined in the class:
Polynomial operator+=(const Polynomial &other);
Then your non-member implementation will just be:
Polynomial operator+(Polynomial a, const Polynomial &b)
{
a+=b;
return a;
}
If you insist on using the function as defined in your code, then you will need to make it a
friend if you need access to private members:
Polynomial operator+(Polynomial &a, Polynomial &b)
{
Polynomial p;
// add them as needed
return p;
}
My Matrx class is defined as
class Matrx
{
double A[50][50];
int m,n;
public:
Matrx(void);
Matrx(int a, int b)
{
m=a;
n=b;
}
Matrx operator +(Matrx b);
Matrx Transpose(Matrx b);
Matrx operator *(Matrx b);
CString printMatrx();
void readMatrx(double a[][]);
Matrx TransposeMat(Matrx b);
};
void Matrx::readMatrx(double a[][])
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=a[i][j];
}
}
The intellisense gives error like the below
1 IntelliSense: an array may not have elements of this type d:\bmadaptive_dd_v1.02\matrx.h 17 27 TestServer
Why?
How to pass a two dimensional array as argument of the function?
The problem is that when passing multidimensional arrays as parameters in C++, you must specify the dimension of the outermost array. For example:
void ThisIsIllegal(int arr[][]); // Wrong!
void ThisIsAlsoIllegal(int arr[10][]); // Also wrong
void ThisIsLegal(int arr[][10]); // Okay
If you want to be able to have a function that takes in an array of any size, you can use templates:
template <size_t N, size_t M>
void ThisIsAlsoLegal(int (&arr)[M][N]);
This last version accepts any multidimensional array of the right type, and is probably what you're looking for.
You need to properly learn about arrays and pointers. This includes the lesson "huh! They are not as useful as I thought they were". After you've gotten familiar with how arrays and pointers work exactly you should rethink your design.
For example, in my opinion, the following design has lots of advantages:
#ifndef MATRIX_HPP_INCLUDED
#define MATRIX_HPP_INCLUDED
#include <vector>
#include <algorithm>
class matrix
{
public:
typedef std::vector<double>::size_type st;
matrix() : rows_(0), cols_(0) {}
matrix(int r, int c) : rows_(r), cols_(c), coeffs_(st(r)*c,0.0) {}
void reset(int r, int c)
{ rows_=r; cols_=c; coeffs_.clear(); coeffs_.resize(st(r)*c,0.0); }
int rows() const {return rows_;}
int cols() const {return cols_;}
double const& operator()(int i, int j) const {return coeffs_[indexof(i,j)];}
double & operator()(int i, int j) {return coeffs_[indexof(i,j)];}
double const* operator[](int i) const {return &coeffs_[indexof(i,0)];}
double * operator[](int i) {return &coeffs_[indexof(i,0)];}
void swap(matrix& that)
{
std::swap(this->rows_,that.rows_);
std::swap(this->cols_,that.cols_);
this->coeffs_.swap(that.coeffs_));
}
private:
int rows_, cols_;
std::vector<double> coeffs_;
st indexof(int i, int j) const {return st(i)*cols+j;} // row major storage
};
inline void swap(matrix& a, matrix& b) {a.swap(b);}
matrix& operator+=(matrix& lhs, matrix const& rhs);
matrix operator+(matrix const& lhs, matrix const& rhs);
matrix operator*(matrix const& lhs, matrix const& rhs);
inline matrix& operator*=(matrix& lhs, matrix const& rhs)
{ matrix tmp = lhs * rhs; swap(tmp,lhs); return lhs; }
...
#endif
This way you won't waste any space for small matrices, and you can support large matrices. Also, the use of std::vector instead of a pointer member which points to dynamically allocated memory removes the need to define your own copy constructor, assignment operator and destructor.
Of course, you could use boost::multi_array as a matrix replacement but using a custom matrix class allows you to declare overloaded operators in your own namespace which is desirable due to ADL (argument dependent lookup).
You might think that this doesn't really answer your question. In that case, let me stress that I think you don't fully understand how arrays and pointers work / behave. This is something you should look up in a decent C++ book. One could write many pages about this topic. You can't expect to see a short answer explaining all the quirks.
Check out the Definite C++ Book Guide thread.
You need to specify all but the first dimension, e.g.
void Matrx::readMatrx(double a[][50])
From this you should be able to see that you have a fundamental problem with the way you have implemented your class, but at least you should now be able to get the code to compile.
You can to specify all dimensions or only last dimension to pass an array:
void Matrx::readMatrx(double a[][50])
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=a[i][j];
}
}
Thanks to all of you people...you were really helping...I have found myself a new definition of the class and the function definition for the matrix that fitted my need. I need you r comment on it...Below is the example of the class declaration..
#include<iostream>
#include"stdafx.h"
using namespace std;
const int M=100; const int N=100;
class Matrix
{
double A[M][N];
int m,n;
public:
Matrix(void);
Matrix(int a, int b)
{
m=a;
n=b;
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)
A[i][j]=0.0;
}
}
Matrix operator +(Matrix b);
Matrix operator -(Matrix b);
Matrix operator *(Matrix b);
void TransPose(Matrix b);
CString printMatrix();
void readMatrix(double*);
};
and then the function implementation
#include "stdafx.h"
#include "Matrix.h"
Matrix::Matrix(void)
{
}
Matrix Matrix::operator *(Matrix b)
{
Matrix c(m,m);
if(n!=b.m)
{
HWND hndOwner(0);
MessageBoxW(hndOwner,L"Multiplication not possible row and column does not match",L"Error",NULL);
Matrix errMat(1,0);
double er[1][1]={0}; errMat.readMatrix((double *)er);
return errMat;
}
for(int i=0;i< m;i++)
{
for(int k=0;k< m;k++)
{
c.A[i][k]=0;
for(int j=0;j< n;j++)
{
c.A[i][k] = c.A[i][k]+(A[i][j] * b.A[j][k]) ;
}
}
}
return c;
}
Matrix Matrix::operator +(Matrix b)
{
Matrix c(m,n);
if((n!=b.n)||(m!=b.m))
{
HWND hndOwner(0);
MessageBoxW(hndOwner,L"Addition not possible row and column does not match",L"Error",NULL);
Matrix errMat(1,0);
double er[1][1]={0}; errMat.readMatrix((double *)er);
return errMat;
}
for(int i=0;i<m;i++)
{
for(int j=0;j< n;j++)
{
c.A[i][j]=0.0;
}
}
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
{
c.A[i][j]=A[i][j]+b.A[i][j];
}
}
return c;
}
CString Matrix::printMatrix()
{
CString strB(" "),strDisp;
for(int iRow=0;iRow<m;iRow++)
{
for(int iColumn=0;iColumn<n;iColumn++)
{
strB.Format(L"%lf ",A[iRow][iColumn]);
strDisp+=strB;
}
strDisp+="\r\n";
}
return strDisp;
}
void Matrix::readMatrix(double *ptrarr)
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=*(ptrarr+i*n+j);
}
}
void Matrix::TransPose(Matrix b)
{
for(int i=0;i<b.n;i++)
{
for(int j=0;j<b.m;j++)
A[i][j]=b.A[j][i];
}
}
The simple codes in the above are working well till now...if you have any suggestion for the improvement please suggest..
You're lucky, then because:
for(int j=0;j<m;j++)
A[i][j]=0.0;
should probably be:
for(int j=0;j<**n**;j++)
A[i][j]=0.0;