How to overload + operator in a heap allocated var - c++

class a{
int *var = new int;
public:
//constructor and destructor
a(int a):var(new int(5)){}
~a() {delete var;}
int get() const {return *var}
//overload of + oporator
a operator+(const a & rhs){return a(*var+rhs.get()
//overload of ++ operator
a a::operator++ (int)
}
a a::operator+ (const a & rhs) {
return a(*itsRadius + rhs.get());
}
a a::operator++ (int){
a temp(*this);
*itsRadius= *itsRadius+1;
return temp;}
}
now when i do like this:
a c(10),d,g;
g=c+d;
i get g = to some address instead of 15 .
why is that?
and when i fo c++ i get an error (in the distructor when he try to delete),why is that?

Here is a working example. You need also to read about the rule of three:
#include <iostream>
class Int
{
int *_value;
public:
Int(int value) : _value(new int(value))
{
}
~Int()
{
delete _value;
}
Int(Int const &rhs) : _value(new int(*rhs._value))
{
}
Int & operator=(Int const &rhs)
{
*_value = *rhs._value;
return *this;
}
Int operator+(Int &rhs) const
{
return Int(*rhs._value + *_value);
}
operator int() const
{
return *_value;
}
};
int main(void)
{
Int a(10),
b(32),
c(a + b);
std::cout << c << "\n";
a = c;
std::cout << a << "\n";
}
And also, it is a bad idea to use raw C pointers in C++. Read about the std::unique_ptr.

o.k. so i solve the problem , this is the working code :
class SimpleCircle {
int *itsRadius;
public:
SimpleCircle():itsRadius(new int(5)) { cout << "constructor initialized" << endl;}
SimpleCircle(int num) { itsRadius = new int(num); cout << "constructor" << endl;}
SimpleCircle(const SimpleCircle &rhs) : itsRadius(new int(*rhs.itsRadius)){ cout << "copy constructor" << endl; }
~SimpleCircle(){ delete itsRadius; cout << "destructor" << endl;}
//perfect
int get() const {return *itsRadius;}
void set(int num) { *itsRadius = num;}
//-------
//plus operator
SimpleCircle operator+(const SimpleCircle &);
//inc operator
SimpleCircle operator++();
SimpleCircle operator++(int);
//= operator
SimpleCircle & operator=(const SimpleCircle &);
};
SimpleCircle SimpleCircle::operator+ (const SimpleCircle & rhs) {
return SimpleCircle(*itsRadius + *rhs.itsRadius);
}
SimpleCircle SimpleCircle::operator++() {
int a = *itsRadius;
++a;
*itsRadius=a;
return *this;
}
SimpleCircle SimpleCircle::operator++ (int){
SimpleCircle temp(*this);
*itsRadius= *itsRadius+1;
return temp;
}
SimpleCircle & SimpleCircle::operator= (const SimpleCircle & rhs) {
if (this == &rhs)
return *this;
*itsRadius = *rhs.itsRadius;
return *this;
}
int main()
{
SimpleCircle a;
cout << a.get() << endl;
SimpleCircle b(15);
cout << b.get() << endl;
SimpleCircle c = a + b;
cout << "a: "<< a.get() << endl;
cout << "b: " << b.get() << endl;
cout << "c: " << c.get() << endl;
a++;
cout << "a: " << a.get() << endl;
++a;
cout << "a: " << a.get() << endl;
now the reason in the former code i had 2 problem (that was 1 becoase of the outher)
1 c was equal to some garbege instead of a number
2 the program break in the end destructor
the reason was i forgat o add a operator= , so it didn't know how to treat to :
c=a+b;
after i fixed it , all come together nicely

Related

why is this code not detecting << operator?

Please explain to me why this is not detecting the << operator.
I tried my best, even tried to overload << on both classes (which is not necessary).
#include<iostream>
using namespace std;
const int MAX = 10;
class Complex;
template<class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return NULL;
}
else {
//return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) { real = r; imag = i; }
friend ostream& operator << (ostream& s, Complex& c);
};
ostream& operator << (ostream& s, Complex& c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
//cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
The function signature should be something like:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
And the function pop can't return NULL since the type is not the same as t. Fixed code might like:
#include <iostream>
using namespace std;
const int MAX = 10;
class Complex;
template <class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return {}; // May throw, or return std::optional here
} else {
// return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) {
real = r;
imag = i;
}
friend ostream &operator<<(ostream &s, const Complex &c);
};
ostream &operator<<(ostream &s, const Complex &c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
// cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
Online demo.
Related question: What are the basic rules and idioms for operator overloading?
It doesn't work because the second parameter should be a const reference
class Complex{
private:
float real,imag;
public:
Complex(float r=0.0,float i=0.0){
real=r;
imag=i;
}
friend ostream& operator<<(ostream& s, const Complex& c);
};
ostream& operator<<(ostream& s, const Complex& c) {
s<<"("<<c.real<<","<<c.imag<<")";
return s;
}
Reason:
The pop function returns an r-value. You can think of an r-value as a nameless object in memory (of course, there is more to it). You cannot put an r-value into an l-value reference. But for a const reference, it does not matter, since you are not going to modify it.
Solution 1:
friend ostream &operator<<(ostream &s, Complex &c); // accepts lvalue - c refers to some external Complex object.
friend ostream &operator<<(ostream &s, Complex &&c); // accepts rvalue - c becomes a normal local variable whose value is the passed rvalue.
Solution 2:
friend ostream &operator<<(ostream &s, const Complex &c); // accepts both

Difference Visual and GDBonline answer?

I have a problem, when i start a program in visual studio that i got this like an answer:
Token()
Operator+
Token(Token&&)
~Token(): 4
Operator=
~Token(): 4
But when i compiled , same source code in GDBonline i got this like an answer:
Token()
Operator+
Operator=
~Token(): 4
I want to ask you which answer is a good one?
#include <iostream>
using namespace std;
class Token{
public:
int a{1};
Token(){ //default constructor
cout << "Token()" << endl;
};
Token(int a0): a{a0} { //parametric constructor
cout << "Token(int)" << endl;
}
Token(const Token& t){ //copy constructor
this->a = t.a;
cout << "Token(const Token&)" << endl;
}
Token(Token&& t) noexcept{ //move constructor
this->a = t.a;
cout << "Token(Token&&)" << endl;
}
Token& operator=(const Token& t0){ //operator =
this->a = t0.a;
cout << "Operator=" << endl;
return *this;
}
Token operator+(const Token& t0){ //operator +
Token t;
t.a = this->a + t0.a;
cout << "Operator+" << endl;
return t;
//return Token{this->a + t0.a};
}
~Token(){ //destructor
cout << "~Token(): " << this->a << endl;
};
};
int main(){
Token t0;
Token t1{3};
Token t2;
t0 = t1 + t2;
return 0;
}

Cannot sort std::vector using lambda with const reference

I want to sort a vector according to the custom datatype. I followed Sorting a vector of custom objects
answer. I am using lambda function to compare the objects. However I am getting compiler errors as following while sorting:
/usr/include/c++/7/bits/stl_algo.h:1852: error: cannot bind non-const lvalue reference of type 'MyData&' to an rvalue of type 'std::remove_reference::type {aka MyData}'
*__first = _GLIBCXX_MOVE(__val);
^
main.cpp
#include "mydata.h"
#include <vector>
int main()
{
std::vector<MyData> tv {MyData(2,21), MyData(3,20), MyData(10,100), MyData(9,20)};
std::sort(tv.begin(), tv.end(), []( MyData const& lhs, MyData const& rhs ){
return lhs.get_size() < rhs.get_size();
});
return 0;
}
mydata.cpp
#ifndef MYDATA_H
#define MYDATA_H
#include <iostream>
#include <algorithm>
class MyData
{
private:
int *m_data;
int m_x;
size_t m_size;
public:
MyData(const size_t &size,int const &x):
m_data(new int[size]),
m_x(x),
m_size(size)
{
std::fill_n(m_data,m_size, m_x);
std::cout << *m_data << " ctor" << m_size << std::endl;
}
MyData(const MyData& other):
m_data(new int[other.m_size]),
m_x(other.m_x),
m_size(other.m_size)
{
std::fill_n(m_data,m_size, m_x);
std::cout << *m_data << " cctor" << m_size << std::endl;
}
MyData& operator=(MyData& other)
{
std::cout << *m_data << " cbctor" << m_size << std::endl;
swap(*this,other);
std::cout << *m_data << " cactor" << m_size << std::endl;
return *this;
}
~MyData(){
std::cout << *m_data << " dtor" << m_size << std::endl;
delete[] m_data;
}
size_t get_size() const{
return m_size;
}
friend void swap(MyData& first, MyData& second){ // (1)
std::swap(first.m_size, second.m_size);
std::swap(first.m_x, second.m_x);
std::swap(first.m_data, second.m_data);
}
friend std::ostream& operator<< (std::ostream& stream, const MyData& mydata) {
stream << *(mydata.m_data) << " " << mydata.m_size << " "<< mydata.m_x;
return stream;
}
};
#endif // MYDATA_H
I do not understand the error. I am not changing the value of the reference, why I am getting this error.
I also read this but did not understand why it is occurring here.
Thank you.
There can be some type of declarations copy assignment operator.
It is typical declaration of a copy assignment operator when copy-and-swap idiom can be used:
MyData& operator=(MyData other);
It is typical declaration of a copy assignment operator when
copy-and-swap idiom cannot be used (non-swappable type or degraded
performance):
MyData& operator=(const MyData& other);
So to use swap in your realization you can declare copy assignment operator as MyData& operator=(MyData other);
You should modify your code like this :
#include <iostream>
#include <fstream>
#include <thread>
#include <atomic>
#include <algorithm>
#include <vector>
using namespace std;
class MyData
{
private:
int *m_data;
int m_x;
size_t m_size;
public:
MyData(const size_t &size, int const &x) :
m_data(new int[size]),
m_x(x),
m_size(size)
{
std::fill_n(m_data, m_size, m_x);
std::cout << *m_data << " ctor" << m_size << std::endl;
}
MyData(const MyData& other) :
m_data(new int[other.m_size]),
m_x(other.m_x),
m_size(other.m_size)
{
std::fill_n(m_data, m_size, m_x);
std::cout << *m_data << " cctor" << m_size << std::endl;
}
MyData& operator=(const MyData& other)
{
std::cout << *m_data << " cbctor" << m_size << std::endl;
//swap(*this, other);
if (this != &other)
{
this->m_data = new int[other.m_size];
for (size_t i = 0; i < other.m_size; ++i)
{
this->m_data[i] = other.m_data[i];
}
this->m_x = other.m_x;
this->m_size = other.m_size;
}
std::cout << *m_data << " cactor" << m_size << std::endl;
return *this;
}
~MyData() {
std::cout << *m_data << " dtor" << m_size << std::endl;
delete[] m_data;
}
size_t get_size() const {
return m_size;
}
friend void swap(MyData& first, MyData& second) { // (1)
std::swap(first.m_size, second.m_size);
std::swap(first.m_x, second.m_x);
std::swap(first.m_data, second.m_data);
}
friend std::ostream& operator<< (std::ostream& stream, const MyData& mydata) {
stream << *(mydata.m_data) << " " << mydata.m_size << " " << mydata.m_x;
return stream;
}
};
int main()
{
std::vector<MyData> tv{ MyData(2,21), MyData(3,20), MyData(10,100), MyData(9,20) };
std::sort(tv.begin(), tv.end(), [](MyData const& lhs, MyData const& rhs) {
return lhs.get_size() < rhs.get_size();
});
std::system("pause");
return 0;
}

Operator overloading =, *=. How to make this work?

I have problem with those lines in main:
*tab[1]=test1;
*tab[4]=test2;
It just adds colour, and variables (a,b,h) stay the same. I was trying something like this
cuboid operator=(const cuboid & base)
{
return cuboid(base.colour(), base.valueA(), base.valueB(),base.h_)
}
but this doesn't seem to be working either
next one is this:
*tab[4] * =2;
There is overloaded operator for this method and when I run this there occures some error. No match for operator*=. Operand types are figure and int.
The last one is: *tab[2] = "bright" + *tab[2]; I think that I need a new constructor for this, but where do I make one?
Thanks for any answer !!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
using namespace std;
class figure
{
string * colour_;
public:
figure(): colour_(new string("Empty")) {}
figure(const string & colour): colour_(new string(colour)) {}
figure(const figure & base)
{
colour_=new string(*base.colour_);
}
virtual ~figure() {delete colour_;}
string & colour () const {return *colour_;}
virtual double area () =0;
virtual void print(ostream& where) const
{
where << "Colour: " << colour() << " ";
}
friend ostream & operator <<(ostream &os, const figure & base)
{
base.print(os);
return os;
}
figure & operator=(const figure & base)
{
if(this==&base)
return *this;
else
{
colour_=new string(*base.colour_);
return *this;
}
}
};
class circle :public figure
{
int r_;
public:
circle() : r_(0) {}
circle(const string & colour,const int r) : figure(colour), r_(r) {}
double area()
{
return M_PI*r_*r_;
}
const int & radius() const {return r_;}
void print(ostream& where) const
{
where << "Colour: " << colour() << " ";
where << "Radius: " << radius() << " ";
}
circle & operator=(const circle & base)
{
r_=base.r_;
figure::operator=(base);
return *this;
}
};
class rectangle : public figure
{
int a_;
int b_;
public:
static int ObjectCount_;
rectangle() : a_(0), b_(0) {++ObjectCount_;}
rectangle(const string & colour, const int a, const int b) : figure(colour),a_(a), b_(b) {++ObjectCount_;}
~rectangle() {--ObjectCount_;}
double area()
{
return a_*b_;
}
const int & valueA () const {return a_;}
const int & valueB () const {return b_;}
int & changeA() {return a_;}
int & changeB() {return b_;}
void print(ostream& where) const
{
where << "Colour: " << colour() << " ";
where << "Value A: " << valueA() << " ";
where << "Value B: " << valueB() << " ";
}
rectangle & operator=(const rectangle & base)
{
a_=base.a_;
b_=base.b_;
return *this;
}
static int & ObjectCount() {return ObjectCount_; }
};
class cuboid :public rectangle
{
int h_;
public:
cuboid() : h_(0) {}
cuboid(const string & colour, const int a, const int b, const int h) : rectangle(colour,a,b), h_(h) {}
double area()
{
return 2*valueA()*valueB()+2*valueB()*h_+2*valueA()*h_;
}
void print(ostream& where) const
{
where << "Colour: " << colour() << " ";
where << "Value A: " << valueA() << " ";
where << "Value B: " << valueB() << " ";
where << "Height: " << h_ << " ";
}
cuboid & operator=(const cuboid & base)
{
figure::operator=(base);
rectangle::operator=(base);
h_=base.h_;
return *this;
}
cuboid & operator*=(const int number)
{
h_*=number;
changeA()*=number;
changeB()*=number;
return *this;
}
};
int rectangle::ObjectCount_=0;
int main()
{
figure * tab[5];
const circle test1("black",100);
const cuboid test2("grey", 2,2,2);
tab[0]=new circle("red",1);
tab[1]=new circle;
tab[2]=new rectangle("blue",1,1);
tab[3]=new cuboid("green",1,1,1);
tab[4]=new cuboid;
for(unsigned i=0; i<5;++i)
cout << tab[i]->area() << endl;
for(int i=0; i<5; ++i)
cout<<*tab[i]<<tab[i]->area()<<"\n";
cout << "***********************" << endl;
*tab[1]=test1; // it just assigns a colour, rest stays the same
*tab[4]=test2; // same here
/*
*tab[2] = "bright" + *tab[2]; //?????
*/
//*tab[4]*=2; //some error, no idea
for(int i=0; i<5; ++i)
cout<<*tab[i]<<tab[i]->area()<<"\n";
cout << "$ " << rectangle::ObjectCount() << endl;
for(int i=0; i<5; i++)
delete tab[i];
cout << "$ " << rectangle::ObjectCount() << endl;
}
You are defining array figure* tab[5], so then you make an assigments you are casting all pointers to your objects to figure*:
tab[0]=new circle("red",1);
tab[1]=new circle;
tab[2]=new rectangle("blue",1,1);
tab[3]=new cuboid("green",1,1,1);
tab[4]=new cuboid;
Class figure have only this assigment operator:
figure & operator=(const figure & base) {
if(this==&base)
return *this;
else {
colour_=new string(*base.colour_);
return *this;
}
}
So, then you are doing:
*tab[1]=test1;
*tab[4]=test2;
you are calling that assigment operator from class figure.
Same with operator *=. class figure just doesn't
have it. Thats why you are getting error.

Upcasting and Stream Operator Overloading

As you can see, only the overloaded version of the stream insertion operator for the base class is called on both instances. I understand why it's so. It's because there is no dynamic binding. But, how do I fix it?
#include <iostream>
using namespace std;
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') {
this->i = i;
this->c = c;
}
int getI() { return i; }
char getC() { return c; }
friend ostream& operator << (ostream&, A&);
};
class B : public A {
double d;
public:
B(int i = 0, char c = ' ', double d = 0.0) : A(i, c), d(d) {}
friend ostream& operator << (ostream&, B&);
};
ostream& operator << (ostream& out, A& a) {
out << "\nInteger: " << a.i << "\nCharacter: " << a.c << endl;
return out;
}
ostream& operator << (ostream& out, B& b) {
out << "\nInteger: " << b.getI() << "\nCharacter: " << b.getC() << "\nDouble: " << b.d << endl;
return out;
}
int main() {
A* a = new A (10, 'x');
B* b = new B(20, 'y', 5.23);
A* array[] = { a, b };
cout << *(array[0]);
cout << "\n______________________________\n";
cout << *(array[1]);
delete a;
delete b;
cin.get();
return 0;
}
How can I make cout << *(array[1]); call the overloaded stream insertion operator that takes an object of B as one of it's arguments?
You can't make it call the overloaded operator, since overloading is resolved at compile time.
To do resolution at runtime, i.e. use dynamic dispatch, you need to move the code that does the printing to a virtual member function.
Then call that from the operator (you only need one, for the base class).
class A
{
public:
// ...
// Override this in B
virtual void print(std::ostream& o) const
{
o << "\nInteger: " << i << "\nCharacter: " << c << endl;
}
// ...
};
ostream& operator << (std::ostream& out, const A& a) {
a.print(out);
return out;
}