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...
Related
I want to build my own full Vector class in C++. I started like this:
#include <iostream>
#include <initializer_list>
#define Print(x)(std::cout<< x << std::endl)
// Vector Class //
template <typename T>
class Vector
{
// Attributes
int length = 0;
T* array;
public:
// Default constructor
Vector()
: length(0), array(nullptr)
{ }
// Copy constructor
template<typename U>
Vector(const Vector<U>& other)
: Vector(other.len())
{
Print("Use Copy Constructor");
// Coppying other data to new array
array = new T[other.len()];
for (auto i=0; i < other.len(); i++)
array[i] = other[i];
}
// Move constructor
Vector(Vector<T>&& other)
: length(other.len()), array(other.array)
{
Print("Use Move Constructor");
// Deleting other array
other.length = 0;
other.array = nullptr;
}
// Constructor (does not allow uniform initialisation)
Vector(int length)
: length(length), array(new T[length])
{ }
// Constructor (with initialiser list and delegate constructor)
Vector(std::initializer_list<T> list)
: Vector((int)list.size())
{
std::uninitialized_copy(list.begin(), list.end(), array);
}
// Destructor
~Vector()
{
length = 0;
delete[] array;
array = nullptr;
}
// Function Len that returns the length
int len() const
{
return length;
}
// Operator[](int i) and its const overload
auto& operator[](int i)
{
return array[i];
}
auto& operator[](int i) const
{
return array[i];
}
// Copy assignment operator
template<typename U>
Vector& operator=(const Vector<U>& other)
{
Print("Use Copy Operator");
if (this != (Vector*)& other) {
/*
This works the same way but does not solve the problem:
Vector<typename std::common_type<T,U>::type> temp(other);
temp.swap(*this);
*/
delete[] array;
length = other.len();
array = new T[other.len()];
for (auto i = 0; i < other.len(); i++)
array[i] = other[i];
}
return *this;
}
// Move assignment opertator
Vector& operator=(Vector<T>&& other)
{
Print("Use Move Operator");
if (this != (Vector*)&other){
/*
This works the same way but does not solve the problem:
Vector<T> temp(std::move(other)); // moves the array
temp.swap(*this);
*/
delete[] array;
length = other.len();
array = other.array;
other.len() = 0;
other.array = nullptr;
}
return *this;
}
};
But if I now try to use the copy assignment operator like this:
Vector<double> double_vector = {3.4677, 3.212, 2.2, 6.3};
Vector<double> a = double_vector;
I get the following error message:
error: use of deleted function 'constexpr Vector<double>::Vector(const Vector<double>&)'
I assume that the problem lies within the copy constructor and copy assignment operator, but I sadly can't find a solution. What I find strange is that, if I comment out the move constructor and move assignment operator, the code does seem to work. This lets me think that the compiler has difficulty knowing which constructor to use. But I could also be very wrong about this.
Hope I gave enough info for an answer/push in the right direction.
A template is never a copy constructor, that is a converting constructor.
And as you have defined a bunch of other constructors, the otherwise default copy constructor will be defined as deleted.
Why is bool casting being called ?
The problem appears when the constructor Set result(*this) is called. I expect it to use the Copy Constructor, instead it casts *this to bool and uses it as an int for the constructor.
How to fix it to use the copy constructor?
Set Set::operator+(const Set& rhs)const
{
Set result(*this);
for (unsigned int i = 0; i < rhs.getSize(); i++)
{
result.add(rhs[i]);
}
return result;
}
Set::operator bool()const
{
return !!(*this);
}
Set::Set(size_t capacity)
{
data = new int[capacity];
size = 0;
this->capacity = capacity;
}
void Set::copy(const Set& copied)
{
size = copied.getSize();
capacity = copied.getCapacity();
if (data != nullptr)
delete[]data;
data = new int[capacity];
for (unsigned int i = 0; i < size; i++)
data[i] = copied.getAt(i);
}
Set::Set(Set& copied)
{
copy(copied);
}
Set& Set::operator=(const Set& copied)
{
if (this != &copied)
copy(copied);
return *this;
}
int& Set::getAt(unsigned int idx)const
{
if (idx < 0 || idx >= size)
throw "Invalid index\n";
return data[idx];
}
bool Set::operator !()const
{
if (size == 0)
return true;
return false;
}
The argument for your copy constructor Set::Set(Set& copied) is not a const reference. The operator Set Set::operator+(const Set& rhs)const is const so this is a const Set * and *this is a const Set. Since you cannot pass a const T to a T& argument (it would discard the const) you may not make use of the copy constructor in this context.
To fix this, make your copy constructor accept const Set & instead, just like the copy member function does :
Set::Set(const Set& copied)
// ^^^^^ Added const here
{
copy(copied);
}
Edit : Mandatory disclaimer that you should not have to write your own dynamically sized array. Use std::vector instead. It will greatly simplify your type and will probably be far safer.
You can declare casting operator explicit to avoid implicit casting to bool:
explicit operator bool() const {
...
}
And then use it like this:
Set::bool(//obj_name);
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 am trying to make a bag container. The problem that beyond me occurs when I am overloading the = operator.
Zsak& Zsak::operator =(const Zsak& a)
{
(*this).V=a.V;
(*this).elemsz=a.elemsz;
return *this;
}
with this header:
class Zsak
{
public:
Zsak (){V=new Elem[100];}
Zsak (const Zsak & a)
{
*this=a;
}
Zsak(int meret)
{
V=new Elem[meret];
}
~Zsak(){delete[] V;}
Zsak& operator -(const Zsak& b);
Zsak& operator =(const Zsak& a);
void Zsak_Ba(int e);
void Zsak_Bol(int e);
bool Uress();
int E_Hany(int e) const;
friend std::ostream& operator << (std::ostream& out,const Zsak& z);
private:
Elem *V;
int elemsz=0;
};
The Zsak_Ba puts an element into the bag;
The Zsak_Bol draws out an element from the bag;
What I observed through testing is that the address of const Zsak a identify with the address of *this .
with this context
Zsak z(5),c(5);
z.Zsak_Ba(1);
z.Zsak_Ba(1);
z.Zsak_Ba(1);
z.Zsak_Ba(2);
z.Zsak_Ba(2);
z.Zsak_Ba(2);
z.Zsak_Ba(4);
Zsak d=z;
d.Zsak_Bol(1);
cout<<z<<endl<<d;
It prints :
1 2
2 3
4 1
1 2
2 3
4 1
And what it really should print is:
1 3
2 3
4 1
1 2
2 3
4 1
What i should do to obtain this?
What i am doing wrong? And why?
Thanks a lot!
You are only copy the pointers (and not the content) in you assignment operator.
Zsak& Zsak::operator =(const Zsak& a)
{
if (this == &a) { // or std::addressof(a)
return *this;
}
delete[] V;
elemsz=a.elemsz;
V=new Elem[elemsz];
for (std::size_t i = 0; i < elemsz; ++i) {
V[i] = a.V[i];
}
return *this;
}
Additionally, I don't see where the elemsz is being updated (outside the member initialisation). I would imagine it would be in constructors.
Zsak(int meret)
{
V=new Elem[meret];
elemsz = meret;
}
And
Zsak ()
{
V=new Elem[100];
elemsz = 100;
}
It may also be worth noting that often a "copy-swap" is used to implement the assignment operator, and a full copy in the copy constructor (basically the other way around from what you have it).
The "copy-swap" would look like
Zsak (const Zsak & a) : elemsz(a.elemsz)
{
V = new Elem[elemsz];
for (int i = 0; i < elemsz; ++i) { // copy the contents
V[i] = a.V[i];
}
}
Zsak& Zsak::operator =(const Zsak& a)
{
Zsak temp(a);
std::swap(this->elemsz, temp.elemsz);
std::swap(this->V, temp.V);
return *this;
}
It incurs some overhead with on assignment to self, a test for self assignment can be added for this if needed.
Understanding that this is a task to use and implement dynamic memory, it may be best to re-factor out the Elem array and its management outside the of the main class. It is generally easier to maintain and correct bugs and issues as they arise.
If you use vector<Elem> instead of manual dynamic memory, you do not need any user-defined copy constructor or assignment operator. It will just work. This is the preferred solution. Let C++ do the work for you.
I must write operator overloading += but I don't know how to do it correctly (I began to write it a the end of code it wasn't correct so i delete all except you see).
#include <iostream>
using namespace std;
class dek
{
private:
int *x,na4,kon,n,razmer;
public:
dek(int m)
{
x=new int[m];
n=m;
na4=1;
kon=0;
razmer=0;
}
~dek()
{
delete [] x;
}
void v_n(int a)
{
if(razmer!=n)
{
na4--;
if(na4<0)na4=n-1;
x[na4]=a;
razmer++;
}
else cout<<"dek polon\n";
}
void v_k(int b)
{
if(razmer!=n)
{
kon++;
if(kon>n-1)kon=0;
x[kon]=b;
razmer++;
}
else cout<<"dek polon\n";
}
int size()
{
return razmer;
}
void u_n()
{
if(razmer!=0)
{
na4++;
if(na4>n-1)na4=0;
razmer--;
}
else cout<<"dek pust\n";
}
void u_k()
{
if(razmer!=0)
{
kon--;
if(kon<0)kon=n-1;
razmer--;
}
else cout<<"dek pust\n";
}
void pe4at()
{
int i=na4;
if(razmer!=0)
{
while(1)
{
cout << x[i] << " ";
if(i==kon)break;
i++;
if(i>n-1)i=0;
}
cout << "\n";
}
}
dek& operator = (dek const& b)
{
if(&b!=this)
{
delete [] x;
x=new int[b.n];
n=b.n;
razmer=b.razmer;
na4=b.na4;
kon=b.kon;
if(razmer!=0)
{
int i=na4;
while(1)
{
x[i]=b.x[i];
if(i==kon)break;
i++;
if(i>n-1)i=0;
}
}
}
return *this;
}
dek const operator +(dek const& b)const
{
dek s(n+b.n);
s.n=n+b.n;
s.razmer=razmer+b.razmer;
s.na4=0;
s.kon=s.razmer-1;
if(razmer!=0)
{
int j=0,i=na4;
while(1)
{
s.x[j]=x[i];
if(i==kon)break;
i++;
if(i>n-1)i=0;
j++;
if(j>s.n-1)j=0;
}
}
if(b.razmer!=0)
{
int j=razmer,i=b.na4;
while(1)
{
s.x[j]=b.x[i];
if(i==b.kon)break;
i++;
if(i>b.n-1)i=0;
j++;
if(j>s.n-1)j=0;
}
}
return s;
}
dek operator +=(dek const& b)
{
}
};
Well, the results of a += b; should be equivalent to a = a + b;;
since you have already defined an operator+, you know what these
semantics are. Once common practice is to define operator+= first,
and then implement operator+ (usually as a free function) in terms of
+=:
MyClass
operator+( MyClass const& lhs, MyClass const& rhs )
{
MyClass results( lhs );
results += rhs;
return results;
}
You then define operator+= to operate directly on the class members:
MyClass&
MyClass::operator+=( MyClass const& other )
{
n += other.n;
razmer += other.razmer;
// ...
return *this;
}
(Although there are good reasons for making it a non-member,
traditionally, operator+= is a member. Probably because operator=
is required to be a member.)
Also, traditionally, operator+= returns a reference, because this
most resembles the behavior of the operator on built-in types.
Finally, on a completely different issue: you're missing a copy
constructor (which in your case means a double deletion if you do copy),
and your operator= is broken (think of what will happen if the x =
new int[b.n]; fails and throws an std::bad_alloc). The classical
solution for this would be to implement deep copy in the copy
constructor (using more or less the same logic you use in setting the
variables in your assignment operator), and in the assignment operator,
to construct a copy, then swap the elements. This isn't strictly
necessary, but whatever you do, you must do the new (and anything else
which may fail) before changing the values in the object being assign.
(If you do this, the test for self assignment is useless; the need for a
test for assignment is usually a signal that the assignment operator is
broken.)
you need to implement void add(const dek &other) - split it out of "+" operator.
you can then implement + as
dek new_dek(*this);
new_dek.add(other);
return new_dek;
And you can implement += as
this->add(other);
return *this;
(assuming you change the return type of += to dek &)