I am practicing with operator overloading and have built a simple calculator.
template <class one> class calc {
int a;
public:
calc() : a(0) {};
calc(const calc& other) : a(other.a) {}
void print() { cout << a; }
calc& operator += (const calc& other);
calc& operator += (const one& i);
calc& operator -= (const calc& other);
calc& operator -= (const one& i);
calc& operator *= (const calc& other);
calc& operator *= (const one& i);
calc& operator /= (const calc& other);
calc& operator /= (const one& i);
const calc& operator - () const;
friend const calc operator + (const calc& our, const calc& other);
friend const calc operator + (const one& i, const calc& other);
friend const calc operator + (const calc& our, const one& i);
};
But unfortunately, when I try to implement the class, it throws the exception:
Unhandled exception at 0x010154C9 in Proctical programming c++
overloading 1.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001,
0x00192F64).
Here is the main:
int main() {
calc <int> one;
one += 2;
one.print();
cin.get();
}
And the problem occurs, for example, here but consequently also in other operators:
template <class one>
calc<one>& calc <one> :: operator += (const one& i) {
*this += i;
return *this;
}
Could you, please, hint me at what I am doing wrong?
Your function calls itself recursively with no condition to exit:
template <class one>
calc<one>& calc <one> :: operator += (const one& i) {
*this += i;
// ^calls the function youre currently in.
return *this;
}
You need to adjust your += operator to use the + operator that you've defined, or as #PaulMcKenzie stated, do the actual addition in += and have + use +=. For example,
template <class one>
calc<one>& calc <one> :: operator += (const one& i) {
a += i;
return *this;
}
seems to work.
You can see a warning about this if your warning level is high enough:
Warning 1 warning C4717: 'calc::operator+=' : recursive on all control paths, function will cause runtime stack overflow
That being said, there are some other problems with your code, like int a should be one a and
friend const calc operator + (const calc& our, const calc& other);
should just be a normal + operator instead of a friend.
Related
I am trying to do operator overloading
My header is:
class Nyble
{
public:
Nyble();
Nyble(const Nyble& n);
Nyble& operator=(const Nyble& n);
~Nyble();
Nyble operator+(const char a);
Nyble operator-(const char a);
Nyble operator+(Nyble& n1);
Nyble operator+();
unsigned char getData();
private:
// Do not change this data
unsigned char data;
}
Source:
#include "Nyble.h"
unsigned char Nyble::getData()
{
return this->data;
}
Nyble Nyble::operator+(const char val)
{
return Nyble(getData()+val);
}
Nyble Nyble::operator-(const char value)
{
return Nyble(value + getData()) ;
}``
I am getting an error saying no suitable constructor exists to convert int to Nyble. If so, what constructor should I declare? Else what changes should I make to the overloading function?
You need to add a constructor for Nyble(getData() + val); and Nyble(value + getData()) to work:
class Nyble {
public:
explicit Nyble(char d); // add this
// ...
};
Nyble::Nyble(char d) : data(d) {} // and the implementation
Though, I recommend that you instead implement operator+ and operator- as free functions and make operator+= and operator-= member functions.
It could look like this:
class Nyble {
public:
Nyble() = default;
explicit Nyble(unsigned char d);
// implement operator+= and operator-= as member functions
Nyble& operator+=(const Nyble& n1);
Nyble& operator-=(const Nyble& n1);
unsigned char getData() const;
unsigned char& getData();
private:
unsigned char data = 0;
};
// operator+ and operator- as free functions:
Nyble operator+(Nyble lhs, const Nyble& rhs);
Nyble operator-(Nyble lhs, const Nyble& rhs);
Nyble::Nyble(unsigned char d) : data(d) {}
// the implementation of the member operator overloads:
Nyble& Nyble::operator+=(const Nyble& rhs) {
data += rhs.data;
return *this;
}
Nyble& Nyble::operator-=(const Nyble& rhs) {
data -= rhs.data;
return *this;
}
unsigned char Nyble::getData() const { return data; }
unsigned char& Nyble::getData() { return data; }
// now the free functions can use the member functions
// `operator+=` and `operator-=`:
Nyble operator+(Nyble lhs, const Nyble& rhs) {
return lhs += rhs;
}
Nyble operator-(Nyble lhs, const Nyble& rhs) {
return lhs += rhs;
}
I' ve been trying to make a small library for working with big integers, just as practice, but I get this error for no apparent reason:
Use of overloaded operator '+' is ambiguous (with operand types 'BigNum::BigInt' and 'int')
This is the class definition:
namespace BigNum {
class BigInt {
public:
BigInt();
BigInt(int64_t n);
BigInt(std::string s);
friend std::istream& operator>> (std::istream& in, BigInt& n);
friend std::ostream& operator<< (std::ostream& out, BigInt n);
friend bool operator< (const BigInt& a, const BigInt& b);
friend bool operator> (const BigInt& a, const BigInt& b);
friend bool operator== (const BigInt& a, const BigInt& b);
friend bool operator!= (const BigInt& a, const BigInt& b);
friend bool operator<= (const BigInt& a, const BigInt& b);
friend bool operator>= (const BigInt& a, const BigInt& b);
operator bool();
explicit operator int();
friend void swap (BigInt& a, BigInt& b);
friend BigInt operator+ (BigInt a, BigInt b);
private:
std::vector<int> digits;
std::size_t number_of_digits;
};
}
And these are the methods used:
BigNum::BigInt::BigInt(int64_t n) {
if (n == 0) {
BigInt();
return;
}
// The number is stored in reverse
for (; n; n /= 10)
digits.emplace_back(n % 10);
number_of_digits = digits.size();
}
std::ostream& BigNum::operator<< (std::ostream& out, BigNum::BigInt n) {
for (auto it = n.digits.rbegin(); it != n.digits.rend(); ++it)
out << *it;
return out;
}
void BigNum::swap (BigNum::BigInt& a, BigNum::BigInt& b) {
BigNum::BigInt temp(a);
a = b;
b = temp;
}
BigNum::BigInt BigNum::operator+ (BigNum::BigInt a, BigNum::BigInt b) {
if (a < b)
BigNum::swap(a, b);
BigNum::BigInt result(a);
int transport = 0;
for (std::size_t i = 0; i < b.number_of_digits; ++i) {
result.digits[i] += b.digits[i] + transport;
transport = result.digits[i] / 10;
result.digits[i] %= 10;
}
if (transport)
result.digits.emplace_back(transport);
++result.number_of_digits;
return result;
}
If I write something like:
BigNum::BigInt a = 2;
BigNum::BigInt b = a + 1;
I get that error. I've made the int typecast explicit, but it didn't help out. I don't want to also make the constructor explicit, as that will mean that I'll no longer be able to assign an int to a BigInt (like I did in the previous example).
How can I fix this?
It's not enough to have one explicit conversion operator, you need to make sure that every conversion to a built-in type is explicit. In particular, you should try
explicit operator bool();
to prevent a + 1 from matching the conversion-then-promotion sequence (int)(bool)a and calling operator+(int, int).
I have the following class (header file):
class Kinetics{
double x;
double y;
double z;
public:
Kinetics();
Kinetics(double x_, double y_, double z_);
Kinetics(const Kinetics & obj);
~Kinetics();
double get_x();
void set_x(double x_);
Kinetics operator + (const Kinetics & obj);
Kinetics operator * (double c);
void operator = (const Kinetics & obj);
};
The operators + and * have been implemented (cpp) as:
Kinetics Kinetics::operator + (const Kinetics & obj){
Kinetics aux(x + obj.x, y + obj.y, z + obj.z);
return(aux);
}
and
Kinetics Kinetics::operator * (double c){
Kinetics aux(x * c, y * c, z * c);
return(aux);
}
Contrary to here:
no match for operator*
I have declared and included the header file in my main program. I get the following message:
main.cpp:11: error: no match for ‘operator*’ in ‘2.0e+0 * v2’
And I cannot figure out why. The line of code that originates this error (main file) is:
Kinetics v4 = 2.0 * v2;
Any advise would be welcome. Thank you.
This is why it is a bad idea to declare most binary operators as member functions - they are asymmetric. You need
class Kinetics;
Kinetics operator *(const Kinetics& k, double c);
Kinetics operator *(double c, const Kinetics&k) { return k*c; }
class Kinetics{
double x;
double y;
double z;
public:
Kinetics();
Kinetics(double x_, double y_, double z_);
Kinetics(const Kinetics & obj);
~Kinetics();
double get_x();
void set_x(double x_);
Kinetics operator + (const Kinetics & obj);
friend Kinetics operator * (const Kinetics& k, double c);
void operator = (const Kinetics & obj);
};
There is a common pattern for implementing binary operators, in terms of the compound assignment operators. This avoids the need for friends, and gets you consistent behavior.
In your case, this looks like this:
class Kinetics {
// all that stuff
public:
Kinetics& operator +=(const Kinetics& rhs) {
// implemented inline for less typing
x += rhs.x;
y += rhs.y;
z += rhs.z;
return *this;
}
Kinetics& operator *=(double rhs) {
x *= rhs;
y *= rhs;
z *= rhs;
return *this;
}
}
// These are non-member, non-friend functions
// Again inline for my convenience
inline Kinetics operator +(Kinetics lhs, const Kinetics& rhs) {
lhs += rhs; // lhs is already a copy
return lhs;
}
inline Kinetics operator *(Kinetics lhs, double rhs) {
lhs *= rhs; // You may be tempted to write "return lhs *= rhs;".
return lhs; // Don't. That would prevent RVO.
}
inline Kinetics operator *(double lhs, Kinetics rhs) {
rhs *= lhs; // Thanks for this being commutative
return rhs; // this implementation works.
}
I have the following class:
class MyInteger
{
private:
__int64 numero;
static __int64 int64Pow(__int64, __int64);
public:
// It doesn't matter how these methods are implemented
friend class MyInteger;
MyInteger(void);
MyInteger(const MyInteger&);
MyInteger(const __int64&);
~MyInteger(void);
static MyInteger const minValue;
static MyInteger const maxValue;
MyInteger& operator = (const MyInteger&);
MyInteger operator + (const MyInteger&) const;
MyInteger operator - (const MyInteger&) const;
MyInteger operator * (const MyInteger&) const;
MyInteger operator / (const MyInteger&) const;
MyInteger& operator += (const MyInteger&);
MyInteger& operator -= (const MyInteger&);
MyInteger& operator *= (const MyInteger&);
MyInteger& operator /= (const MyInteger&);
MyInteger operator % (const MyInteger&) const;
MyInteger& operator %= (const MyInteger&);
MyInteger& operator ++ ();
MyInteger operator ++ (int);
MyInteger& operator -- ();
MyInteger operator -- (int);
bool operator == (const MyInteger&) const;
bool operator != (const MyInteger&) const;
bool operator > (const MyInteger&) const;
bool operator < (const MyInteger&) const;
bool operator >= (const MyInteger&) const;
bool operator <= (const MyInteger&) const;
int toStdInt() const
{
return (int)numero;
}
float toStdFloat() const;
double toStdDouble() const;
char toStdChar() const;
short toStdShortInt() const;
long toStdLong() const;
long long toStdLongLong() const;
unsigned int toStdUInt() const;
__int64 toStdInt64() const;
unsigned __int64 toStdUInt64() const;
unsigned long long int toStdULongLong() const;
long double toStdULongDouble() const;
template<class Type>
Type& operator[](Type* sz)
{
return sz[toStdULongLong()];
}
};
template<class Type>
Type* operator+(const Type* o1, const MyInteger& o2)
{
return ((o1) + (o2.toStdInt()));
}
I'd like to use this class to access array elements like this:
MyInteger myInt(1);
int* intPtr = (int*)malloc(sizeof(int) * N);
intPtr[myInt] = 1;
I thought that the function
template<class Type>
Type* operator+(const Type* o1, const MyInteger& o2)
{
return ((o1) + (o2.toStdInt()));
}
could solve my problem, because as this post reports (Type of array index in C++) "The expression E1[E2] is identical (by definition) to *((E1)+(E2))", but I get the C2677 error ('[' operator: no global operator found which takes type 'MyInteger' (or there is no acceptable conversion))
Can someone clarify me this situation?
Thanks
You may be able to do that by overriding the cast to int of your MyInteger class in a way similar to:
class MyInteger {
...
operator int() const
{
return toStdInt(); /** Your class as an array index (int) */
}
...
}
I'm trying to add two object that they are in the same class.
In the private section of the class I have two int variables
class One {
private:
int num1, num2;
public:
One operator+=(const One&); // - a member operator that adds another One object - to the current object and returns a copy of the current object
friend bool operator==(const One&, const One&); // - a friend operator that compares two One class objects for equality
};
One operator+(const One&, const One&);// - a non-friend helper operator that adds One objects without changing their values and returns a copy of the resulting One
I'm not sure I have a problem on the opeartor+ I guess
One operator+(const One &a, const One &b){
One c,d,r;
c = a;
d = b;
r += b;
r += a;
return r;
}
I think the above code is wrong, but I tried to use like b.num1 and I get compile error
error: 'int One::num1' is private
error: within this context
and I can't use b->num1 as well because the above function is not in the member function section.
error: base operand of '->' has non-pointer type 'const One'
This is how it calls in main
Result = LeftObject + RightObject;
If you have already implemented this member function:
One One::operator+=(const One&);
Then you may implement the non-member addition operator thus:
One operator+(const One& lhs, const One& rhs) {
One result = lhs;
result += rhs;
return result;
}
This can be simplified somewhat into the following:
One operator+(One lhs, const One& rhs) {
return lhs += rhs;
}
This pattern (which you can adapt for all operator/operator-assignment pairs) declares the operator-assignment version as a member -- it can access the private members. It declares the operator version as a non-friend non-member -- this allows type promotion on either side of the operator.
Aside: The += method should return a reference to *this, not a copy. So its declaration should be: One& operator+(const One&).
EDIT: A working sample program follows.
#include <iostream>
class One {
private:
int num1, num2;
public:
One(int num1, int num2) : num1(num1), num2(num2) {}
One& operator += (const One&);
friend bool operator==(const One&, const One&);
friend std::ostream& operator<<(std::ostream&, const One&);
};
std::ostream&
operator<<(std::ostream& os, const One& rhs) {
return os << "(" << rhs.num1 << "#" << rhs.num2 << ")";
}
One& One::operator+=(const One& rhs) {
num1 += rhs.num1;
num2 += rhs.num2;
return *this;
}
One operator+(One lhs, const One &rhs)
{
return lhs+=rhs;
}
int main () {
One x(1,2), z(3,4);
std::cout << x << " + " << z << " => " << (x+z) << "\n";
}
I can't see why the operator+ is wrong:
#include <stdio.h>
class One {
public:
One(int n1, int n2): num1(n1),num2(n2) {}
private:
int num1, num2;
public:
One operator+=(const One& o) {
num1 += o.num1;
num2 += o.num2;
return *this;
}
friend bool operator==(const One&, const One&); // - a friend operator that compares two One class objects for equality
void print() {
printf("%d,%d\n", num1, num2);
}
};
One operator+(const One& a, const One& b) {
One r(0,0);
r += b;
r += a;
return r;
}
int main() {
One a(1,2),b(3,4);
One r = a + b;
r.print();
}