Operator overloading with multiple parameters and symbol - c++

I have a class:
class taphop
{
public:
taphop();
~taphop();
taphop(const list&);
taphop& operator=(const taphop&);
taphop operator+(const int&);
taphop operator+(const taphop&);
};
In main, I can't using multiple parameters:
main()
{
taphop lmc=lmc+2+5+3+2; // Error;
lmc=lmc+3+5+2; // Error;
int a=a+1+2+4+5; // Not error;
a=a+1+2+4+5; // Not error;
return 0;
}

One thing for sure. Below is undefined.
taphop lmc=lmc+2+5+3+2;
As operator+ would be called on the carcass of supposed-to-be-fully-constructed object in expression
lmc+2+5+3+2

In addition to using lmc to initialize lmc, you just need to read the error messages the compiler is giving you. Here is my take on what you might be trying to do:
class taphop
{
int value;
public:
taphop(const int x = 0) :value(x) {} // default value of 0
~taphop() {}
int getvalue() const { return value; }
taphop& operator=(const taphop &r) { value = r.value; return *this; }
taphop operator+(const int x) { return taphop(value + x); }
taphop operator+(const taphop &r) { return taphop(value + r.value); }
};
int main()
{
taphop lmc = taphop(0) + 2 + 5 + 3 + 2;
std::cout << lmc.getvalue() << std::endl; // prints 12
lmc = lmc + 3 + 5 + 2;
std::cout << lmc.getvalue() << std::endl; // prints 22
return 0;
}

Related

addition and subtraction of two numbers using operator overloading

#include<iostream>
using namespace std;
class add
{
private: int a,b;
public: add(int x=0)
{
a=x;
}
add operator+(add const &c) // sub operator-(sub const &c)
{ //{
add sum; // sub diff;
sum.a=a+c.a; // diff.a=a-c.a;
return sum; // return diff
} //}
void print()
{
cout<<"sum: "<<a;
}
};
int main()
{
add a1(10),a2(5); //sub s1(10),s2(5);
add a3=a1+a2; // sub s3=s1-s2;
a3.print(); // s3.print();
return 0;
}
Here I've written seperately but what to do if I need to do both in a single code?
I want a C++ code to perform them simultaneously
You can define any reasonable combination of:
Foo operator+(arg);
Foo operator-(arg);
Foo operator*(arg);
Foo operator/(arg);
And the arg can be another Foo or some other type entirely. For instance:
#include <iostream>
using namespace std;
class Operators {
public:
Operators() = default;
Operators(int v) : value(v) {}
Operators operator+(const Operators &other) {
return Operators{value + other.value};
}
Operators operator+(const int byValue) {
return Operators{value + byValue};
}
Operators operator-(const Operators &other) {
return Operators{value - other.value};
}
Operators operator-(const int byValue) {
return Operators{value - byValue};
}
Operators operator*(const Operators &other) {
return Operators{value * other.value};
}
Operators operator/(const Operators &other) {
return Operators{value / other.value};
}
int value = 0;
};
int main(int, char **) {
Operators first{10};
Operators second{20};
Operators result1 = first + second;
Operators result2 = first * second;
Operators result3 = first * 3;
Operators result4 = second / 2;
cout << "first + second == " << result1.value << endl;
cout << "first * second == " << result2.value << endl;
cout << "first * 3 == " << result3.value << endl;
cout << "first / 2 == " << result4.value << endl;
}
first + second == 30
first * second == 200
first * 3 == 30
first / 2 == 10
You'll see I overwrote operators that take two Operators objects, but I also wrote a few that take an integer argument, too.
I compiled and ran that with:
g++ --std=c++17 Whatever.cpp -o Whatever && Whatever

Strange copy constructor and destructor error

I have a class and i keep getting some error from the destructor.
This is the clas:
#pragma once
class Number
{
int bas;
char* val;
public:
Number(const char* value, int base);
Number(const Number& x);
~Number();
void SwitchBase(int newBase);
void Print();
int GetDigitsCount();
int GetBase();
};
This is the cpp file:
#include "Number.h"
#include <iostream>
Number::Number(const char* value, int base)
{
int a = -1;
do
{
a++;
} while (value[a] != '\0');
val = new char[a + 1];
for (int i = 0; i <= a; i++)
val[i] = value[i];
bas = base;
}
Number::Number(const Number& x)
{
int a = -1;
bas = x.bas;
do
{
a++;
} while (x.val[a] != '\0');
delete[]val;
val = new char[a + 1];
int i;
for (i = 0; i <= a; i++)
val[i] = x.val[i];
}
Number::~Number()
{
delete[]val;
}
void Number::Print()
{
std::cout << "Numarul este: " << val<< std::endl << "Baza este: " << bas<<std::endl;
}
int Number:: GetDigitsCount()
{
int l = 0;
do
{
l++;
} while (val[l] != '\0');
return l;
}
This is the main:
int main()
{
Number x("123", 10),y("111",10),z("0",10);
z = y;
z.Print();
}
I keep getting this error:
Invalid address specified to RtlValidateHeap( 010C0000, 010C8DD8 )
If i do this change in main it works properly but it is not really what I want...
int main()
{
Number x("123", 10),y("111",10);
Number z = y;
z.Print();
}
How can I solve this? I can't figure it out...
Your Number class is missing an assignment operator. Since you use the assignment operator in main the default assignment operator will cause a double delete when you exit main and this explains the error.
It also explains why the error goes away when you change main to use the copy constructor instead of the assignment operator.
You should look at the copy and swap idiom to show how to easily and efficiently implement copy constructors and assignment operators.
Alternatively you could also use std::string instead of manually allocating memory. This would eliminate the need to write a destructor, copy constructor and assignment operator. That's the best solution.
This is an example of how code may look like using std::string:
#include <iostream>
#include <string>
class Number
{
int bas;
std::string val;
public:
Number(std::string, int base);
Number(const Number& number);
Number& operator= (const Number& number);
~Number()=default;
void Print();
int GetDigitsCount();
};
Number::Number(std::string value, int base)
{
val=value;
bas=base;
}
Number::Number(const Number& number)
{
val=number.val;
bas=number.bas;
}
Number& Number::operator= (const Number& number)
{
val=number.val;
bas=number.bas;
return *this;
}
void Number::Print()
{
std::cout << "Numarul este: " << val<< std::endl << "Baza este: " << bas<<std::endl;
}
int Number:: GetDigitsCount()
{
return val.size();
}
int main()
{
Number x("123", 10),y("111",10),z("0",10);
Number k(y);
k.Print();
}

Get "Trigger Breakpoint Error at delete" when using template

I'm using visual studio.
I have 3 class.
It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()
I know it's something up to the pointer in class Rectangle but can't firgure out.
`int main(){
Array<Rectangle>A;
Rectangle a;
cout << a; //It's oke
A.PushBack(a); // problem here
cout<<a;
}`
class Point
{
private:
float _x;
float _y;
public:
float GetX() { return _x; }
float GetY() { return _y; }
public:
Point();
Point(float, float);
Point(const Point&);
~Point() {};
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Point*);
friend ostream& operator<<(ostream&, const Point&);
};
Point::Point() {
_x = 1;
_y = 1;
}
Point::Point(float x, float y) {
_x = x;
_y = y;
}
Point::Point(const Point& a) {
_x = a._x;
_y = a._y;
}
string Point::ToString() const{
stringstream out;
out << "( " << _x << "," << _y << " )";
return out.str();
}
istream& operator>>(istream& in, Point* a) {
cout << "Nhap x: ";
in >> a->_x;
cout << "Nhap y: ";
in >> a->_y;
return in;
}
ostream& operator<<(ostream& out, const Point& a)
{
out << a.ToString();
return out;
}
```
class Rectangle
{
private:
Point* _topleft;
Point* _botright;
public:
void Set_topleft(Point tl) { _topleft = &tl; }
Point Get_topleft() { return *_topleft; }
void Set_botright(Point br) { _botright = &br; }
Point Get_botright() { return *_botright; }
public:
Rectangle();
Rectangle(Point*, Point*);
~Rectangle();
public:
string ToString() const;
public:
friend istream& operator>>(istream&, Rectangle&);
friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
_topleft = new Point(0, 2);
_botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
_topleft = new Point(*a);
_botright = new Point(*b);
}
Rectangle::~Rectangle()
{
delete _topleft;
delete _botright;
}
string Rectangle::ToString() const
{
stringstream out;
out << "A" << *_topleft << "+" << "D" << *_botright;
return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
std::cout << "A( x,y ): ";
in >> a._topleft;
std::cout << "D( x,y ): ";
in >> a._botright;
return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
out << a.ToString();
return out;
}
```
template<class T>
class Array
{
private:
T* _a;
int _len;
public:
Array();
~Array();
public:
int length() { return _len; }
void PushBack(T);
T GetAt(int);
};
template<class T>
Array<T>::Array() {
_a = new T[128];
_len = 0;
}
template<class T>
Array<T>::~Array() {
delete[] _a;
_len = 0;
}
template<class T>
void Array<T>::PushBack(T value) {
if (_len >= 128)
{
std::cout << "Array is over size, which is 128\n";
return;
}
_a[_len] = value;
_len++;
}
template<class T>
T Array<T>::GetAt(int pos) {
return _a[pos];
}
```
The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory.
To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.
Rectangle(const Rectangle &other)
{
if(other._topleft)
_topleft= new Point(*other._topleft);
else
_topleft = nullptr;
if(other._botright)
_botright= new Point(*other._botright);
else
_topleft = nullptr;
}
The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value).
Also, try Rectangle(Rectangle&& o) = delete;

Use of the chain method in the continuation of the copy constructor/initialization in one declaration statements in c++?

As you know, we usually use the return by reference for the method chaining, I use the return by reference in the first code and the output is as I have predicted. In the second code block, when I did not use the return by reference, the chain was broken and my expected output was not generated, but in the third code block, I have reached the desired result using the chain method in continuation of the copy constructor / initialization in one declaration statements (without using return by reference), the question is, what is the logic behind the third code that protects the chain from breaking?
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc& add(int value) { m_value += value; return *this; }
Calc& sub(int value) { m_value -= value; return *this; }
Calc& mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc;
calc.add(5).sub(3).mult(4); // its OK and output 8
std::cout << calc.getValue() << '\n';
return 0;
}
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc add(int value) { m_value += value; return *this; }
Calc sub(int value) { m_value -= value; return *this; }
Calc mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc;
calc.add(5).sub(3).mult(4); // its NOT OK and output 5
std::cout << calc.getValue() << '\n';
return 0;
}
class Calc
{
private:
int m_value;
public:
Calc(int value = 0) : m_value{ value } {}
Calc add(int value) { m_value += value; return *this; }
Calc sub(int value) { m_value -= value; return *this; }
Calc mult(int value) { m_value *= value; return *this; }
int getValue() { return m_value; }
};
int main()
{
Calc calc = Calc{0} // copy constructor / initialization
.add(5) // method chaining
.sub(3) // method chaining
.mult(4); // method chaining, its OK and output 8
std::cout << calc.getValue() << '\n';
return 0;
}
what is the logic behind the third code that protects the chain from breaking?
Chain does get break, but you use the final result to assign to calc
Calc calc = Calc{0}.add(5).sub(3).mult(4);
is equivalent to
Calc calc = Calc{2}.mult(4);
What ultimately gets copy constructed into calc is a temporary Calc object when multiplied by 4.

Operator overloading explanation

I am trying to understand an output of a short program where operator overloading is used.
The output is 137, where the (2+v).print() outputs 13 and 7 is from v.print();
#include <iostream>
using namespace std;
class V
{
int x;
public:
V(int a = 7, int b = 3) { x = a + b; }
void print() { cout << x; }
V operator+(int n)
{
return x++ + ++n;
}
};
V operator+(int lop, V rop)
{
return rop + lop;
}
int main()
{
V v(1, 6);
(2 + v).print();
v.print();
return 0;
}
I understand the basic concept of the operator overloading and I get that V rop is just a copy of the V v(1,6), and it doesn't change the output of v.print(); where x stays 7, but I don't get why it outputs 13, I always get to 10.
The problem is when trying to return an object of type 'V' from this operator:
V operator+(int n)
{
return x++ + ++n;
}
What you're trying to return here in an 'int' so it should be cast to an object of type 'V', the way it's done (casting from a primitive type to custom class) is using constructors. The only constructor you're having is with 2 optional parameters which creates the problem that it tries to make an object of one parameter only, so it's sent as a = 10, b = 3 (default value) and then the output is 13.
I recommend using multiple constructors to solve the problem if you don't want to change the members of the class.
class V
{
int x;
public:
V() { x = 10; }
V(int a) { x = a; }
V(int a, int b) { x = a + b; }
void print() { cout << x; }
V operator+(int n)
{
return x++ + ++n;
}
};
By this way you can call a default constructor which sets x to 10 as you previously did, another constructor with 1 parameter to cast from 'int' to 'V', and your normal constructor that takes a and b.
In your code when arrive at return (x++ + ++n); compiler create an object V so your constructor will be call again. then these assignment will be occurred a=10 and b=3. So you gotta save a and b values in another members.
Try this :
#include <iostream>
using namespace std;
class V {
int x;
int a;
int b;
public:
V(int a=7, int b=3) { x = a + b; this->a = a; this->b = b; }
void print() { cout << x - this->b; }
V operator+(int n) {
return (x++ + ++n);
}
};
V operator+(int lop, V rop) {
return rop + lop;
}
int main()
{
V v(1,6);
(2 + v).print();
v.print();
return 0;
}
Your (2 + v).print(); output will be 10.