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;.
Related
Consider a simple vector class realization:
#include <algorithm>
class Vector {
public:
Vector(int _elementsCount)
: elementsCount(_elementsCount)
, elements(new float[_elementsCount])
{}
~Vector() {
delete[] elements;
}
Vector(const Vector& rhs) {
elementsCount = rhs.size();
elements = new float[elementsCount];
for (int i = 0; i < elementsCount; ++i)
(*this)[i] = rhs[i];
}
float& operator [](int i) {
return elements[i];
}
float operator [](int i) const {
return const_cast<Vector&>(*this)[i];
}
int size() const {
return elementsCount;
}
/*// Dot product
float operator *(const Vector& v) {
float res = 0;
for (int i = 0; i < size(); ++i)
res += (*this)[i] * v[i];
return res;
}*/
private:
int elementsCount;
float* elements;
};
// Multiplication by a scalar
Vector operator *(const Vector& v, float k) {
Vector res(v.size());
for (int i = 0; i < v.size(); ++i)
res[i] = v[i] * k;
return res;
}
// Dot product
float operator *(const Vector& v1, const Vector& v2) {
float res = 0;
for (int i = 0; i < std::min(v1.size(), v2.size()); ++i)
res += v1[i] * v2[i];
return res;
}
void main()
{
Vector v(2);
v * 3; // ambiguous
}
This code compiles. But if we uncomment * operator realization in the class and comment its global realization (dot product function), then there will be an error "'Vector::operator *': 2 overloads have similar conversions", because there is an ambiguity: whether to call the multiplication by a scalar or to interpret 3 as an argument to a parametrized constructor and to call the dot product. This makes sense. But I don't get what's the difference of declaring the * operator as a member function or as a global function. I thought they should be the same in the example like above, but it's not the case.
Added. The thing I most interested in is not how to avoid the ambiguity, but why there is an ambiguity in one case (when * is declared as a member) and there is no one in the other (when * is declared as a global function).
You need to make your constructor explicit:
explicit Vector(int _elementsCount) { ... }
The reason for the ambiguity is that the compiler can't decide whether it should implicitly convert a int value to a Vector and invoke Vector::operator*, or implicitly convert a int value to a float and use operator*(const Vector&, float).
By using explicit, such conversions are forbidden, and you must use Vector(3) if you want "3" to be a Vector.
As a side-note, you should make the operator const, since it does not modify the object. Making it const will also allow it to be used with a const Vector:
float operator *(const Vector& v) const { ... }
Beware that will still conflict with your other overload:
float operator *(const Vector& v1, const Vector& v2)
There is no reason to have both. Choose either the member function or the global function and remove the other.
i have a sparse matrix that is created with two arrays and each array index have a linked list the non zero numbers are in there including the i and j indexs
the header
class MNode {
public:
double _data;
int _indexI, _indexJ; // the place of the node in the matrix
// clarification: _nextRow is a pointer to the next columns in the row
MNode* _nextRow, *_nextCol;
MNode(double data, int i, int j);
};
private:
string _type;
MNode** _rowHead, **_colHead;
int _rowSize, _colSize;
int _elemNum;
void setValue(int, int, double);
void removeElement(int, int);
void insertNode(MNode*);
bool IsExist(int, int);
void setElementByType(int i, int j, double data);
public:
// construct a 'rows X cols' matrix.
SMatrix(int rows, int cols,string type);
// set the (i,j) element to be 'data'
void setElement(int i, int j, double data);
// destroy this matrix.
~SMatrix();
double getElement(int, int);
friend std::ostream& operator<<(std::ostream& os, const SMatrix& mat);
SMatrix& operator = (const SMatrix& other);
SMatrix & operator+(const SMatrix & other) const;
};
the cpp here is the overloading + function i get an erorr
cannot convert this pointer to const SMatrix to Smatrix&
SMatrix &SMatrix::operator +(const SMatrix& other) const {
SMatrix temp(3, 3, "any") ;
if (other._rowSize == this->_rowSize&&other._colSize == this->_colSize&&other._type == this->_type) {
for (int j = 0; j < other._colSize; j++) {
for (int i = 0; i < other._rowSize; i++) {
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
}
}
}
return temp;
}
here is the contructor
SMatrix::SMatrix(int rows, int cols,string matType )
{
_type = matType;
_rowSize = rows;
_colSize = cols;
_elemNum = 0;
_rowHead = new MNode*[rows];
if (!_rowHead)
{
cout << "allocation error";
exit(1);
}
_colHead = new MNode*[cols];
if (!_colHead)
{
cout << "allocation error";
exit(1);
}
for (int i = 0; i < rows; i++)
{
_rowHead[i] = NULL;
}
for (int i = 0; i < cols; i++)
{
_colHead[i] = NULL;
}
}
iam not sure what i need to do the signature of the function is given and cant be chanbged any idea?
You've declared other to be a reference to const:
SMatrix & operator+(const SMatrix & other) const;
^^^^^
You call the member function getElement on that reference:
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
^^^^^^^^^^^^^^^^
You've declared getElement to be non-const:
double getElement(int, int);
^
You may only call const member functions on const references.
the signature of the function is given and cant be chanbged any idea?
If the signature of getElement can't be changed, then you've been dealt a badly written signature. There should be no good reason why a getter couldn't be const. That said, since you're within the class, you can access all members directly without using a getter.
There's another bug. You've declared operator+ to return a reference.
SMatrix &SMatrix::operator +(const SMatrix& other) const
^
But you return a local automatic variable temp:
SMatrix temp(3, 3, "any") ;
// ...
return temp;
Automatic variables are destroyed at the end of the function. Therefore the returned reference will always be dangling and any use of it would have undefined behaviour.
the signature of the function is given and cant be chanbged any idea?
If the signature of operator+ can't be changed, then you've been dealt a badly written signature. The function really should return by value. There's no sensible solution that could return a reference. Using a static local would technically work, but that has some limitations on usage that aren't apparent from the interface.
I have a class to represent two-dimensional array and I want to use () operator for example,
Array arr;
arr(2,5) = 17; // I want to assign 17 as element in 2nd row and 5th column.
I tried something like that: (but is not working)
void operator(int m, int n)(int num) {
int m, n;
p[m][n] = num;
}
i have an operator = (this working):
void operator=(const Array& other) const {
for (int i = 0; i < DIM; i++) {
for (int j = 0; j < DIM; j++) {
p[i][j] = other.p[i][j];
}
}
}
Array class has T** as private member.
How can I overload () operator to access elements in array
Thank You!
You need to build something like
int& operator()(int m, int n)
which returns a reference to the array element, that you can modify through that reference at the calling site.
Don't forget to build the const overload
const int& operator()(int m, int n) const
so you can use similar syntax at a call site for element access for a const object.
Finally, for your assignment operator, you ought not make it const (have you made p mutable?), and you should return a reference to self to help compound assignment:
Array& operator=(const Array& other){
// Your existing code
return *this;
}
Reference: http://en.cppreference.com/w/cpp/language/copy_assignment
I want to overload equal to "=" operator in C++ for
class Array
{
int *p;
int len;
};
All functions/constructor etc. are defined.
My question:
Could someone give me the prototype of the operator overloaded function?
And suppose:
Array a,b;
b=a;
Which of "a" and "b" would be passed implicitly and which explicitly?
Thanks in advance.
The prototype is Array& operator=(const Array& that).
While implementing this, remember about the rule of three and make good use of the copy-and-swap idiom.
You're looking for the assignment operator = (not equal-to, which is operator== and usually serves as an equality comparison)
class Array
{
int *p;
int len;
public:
// Assignment operator, remember that there's an implicit 'this' parameter
Array& operator=(const Array& array)
{
// Do whatever you want
std::cout << "assignment called";
return *this;
}
};
int main(void) {
Array a, b;
a = b;
}
remember that since you wrote "All functions/constructor etc. are defined" you should pay attention to what you need your class to do and possibly also implement destructor as in the rule of three (and/or take a look at its variants in C++11, might be relevant since there's no other code posted).
There is probably more than one way to do it, but here is an option.
Public Functions:
Array::Array(const Array& array)
{
Allocate(0);
*this = array;
}
Array::~Array()
{
Deallocate();
}
const Array& Array::operator=(const Array& array)
{
if (this == &array)
return *this;
Deallocate();
Allocate(array.len);
for (int i=0; i<len; i++)
p[i] = array.p[i];
return *this;
}
Non-Public Functions:
void Array::Allocate(int size)
{
len = size;
if (len > 0)
p = new int[len];
}
void Array::Deallocate()
{
if (len > 0)
delete[] p;
len = 0;
}
Of course, you can always use a vector<int> instead...
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);