Ostream << and operator -= for classes? - c++

I have 2 classes S and M. When I try to use
cout << s3 -= m2;
I get an error that sates:
no operator "-=" matches these operands operand types are: std::ostream -=
class S
{
public:
S& operator-=(M& m)
{
//my code
return *this;
}
}
I tried with 3 parameters, including ostream, but -= has only 2.
How can I fix this?

This has to do with operator precedence. << has a higher precedence than -= so
cout<<s3-=m2;
is treated as
(cout << s3) -= m2;
and not
cout << (s3 -= m2);
You need to use the above form to get what you want.

You have no way to fix this. The operator precedence rules in c++ are fixed and cannot be overloaded.
The only possible solution is to change the using code. For example, if you write
cout << (s3 -= m2);
then your original code should work. Another option is splitting the line in two:
s3 -= m2;
cout << s3;

Related

Returning wrong instances from functions

I'm having trouble figuring out why my BigInt instances along with the custom vector class (BigIntVector) change when returning out of += into + functions. Looking to my example in main.cpp we have 40 + (-30) which in my BigInt.cpp code means it will turn that into 40-30 (and then print negative symbol at end because 'isPositive' bool is false). Using the debugger, I know for certain that -= returns the correct value of 10 into +=. Therefore in += 'tempThis' contains the vector with 10 in it and is returned to + function. However when it returns to the + function, 'tempThis' in that scope becomes 40? Any reason why?
Thank you.
BigInt.cpp addition
// binary addition
BigInt BigInt::operator+(BigInt const& other) const {
BigInt tempThis = BigInt(*this);
tempThis += other; //tempThis becomes 40 which isn't 10 for 40-30!!!!!!!
return tempThis;
}
// compound addition-assignment operator
BigInt BigInt::operator+=(BigInt const& other) {
if (!other.isPositive) {
BigInt tempThis = BigInt(*this);
tempThis -= other; //tempThis is correctly assigned 10 for 40-30!!!!!!!!
cout << "get element at 0 +=: " << tempThis.bigIntVector->getElementAt(0) << endl;
return tempThis;
}
main.cpp
BigInt num11 = -30;
cout << "num11 (-30): " << num11 << endl;
BigInt num12 = 40;
cout << "num12 (40): " << num12 << endl;
BigInt num13 = num12 + num11;
cout << "num13 (-10): " << num13 << endl;
prints:
num11 (-30): -30
num12 (40): 40
num13 (-10): 40
Your compound addition-assignment operator += should be:
modifying its own value; and
returning a reference to itself, not a copy of its value.
The signature should be:
BigInt& BigInt::operator+=(BigInt const& other)
Within it, you don't want to use a temporary value, or possibly if you have failure conditions that might occur and want to guarantee behaviour, use a temporary variable and then overwrite your 'this' object if it succeeds.
Have a look at this page: http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html
for more information. Search within the page for "Compound Assignment Operators" if you don't want to read the whole thing.
You're missing the overload for the assignment operator and you need to return references to BigInt i.e.
BigInt& BigInt::operator+(BigInt const& other) const

Overloading = operator

I wrote the following test program:
int main(int argc, char** argv)
{
ifstream inFile;
inFile.open("D:\\C++\\Assignments\\in1.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
Complex a,b,c;
inFile >> a;
inFile >> b;
ofstream out;
out.open("D:\\C++\\Assignments\\out1.txt");
out << a <<endl<< b<<endl; // dumps data to a stream connected to a file
out << c=a <<endl;
out.close();
return 0;
}
I have overloaded = as following:
void Complex::operator=(const Complex &a)//mulptiplication
{
real=a.real;
imag=a.imag;
}
But I am getting errors like: no match for ooperator <<. Can anyone help with the error?
This is your problem:
out << c=a <<endl;
You need to return a Complex&
Try this:
Complex& Complex::operator=(const Complex &a)//mulptiplication
{
real=a.real;
imag=a.imag;
return *this;
}
The reason is that c=a yields a void and there is no operator<< that works for void on the left hand side
Just for clarity, you might rewrite as:
c = a;
out << c << endl;
ortang is also right that there must be an operator<< for the Complex class.
The problem lies in out << a << endl << b << endl, since you did not overload the operator<< for the Complex class i guess.
Take a look at this SO post how to overload the operator<<.
If real and imag are themselves of types with correct assign semantics (for example primitive types like int or double), then it is redundant and error-prone to implement your own operator=. Just use the compiler-generated one.
Even with proper operators
out << c=a <<endl;
which is parsed as
(out << c) = (a <<endl);
the error occurs, due to operator precedence.

Combining overloaded operators with 'new' object

i'd like to ask something rather difficult for me; I have to make a calendar-type program, but with an overloaded '+=' operator.
So it goes like this:
template<typename T1,typename T2,typename T3> //int,int,int
class T_sort_data{
T1 p1;
T2 p2;
T3 p3;
public:
T_sort_data(){
cout << "\n\t Constructed at [" << this << "]\n";};
/ friend ostream& operator<<(ostream& os,const T_sort_data& obj) // get function
{
os << "\nDay : " << obj.p1 << " \n";
os << "Month : " << obj.p2 << " \n";
os << "Year : " << obj.p3 << " \n";
return os;
}*/
void set_date(){
int dd,mm,yy;
cout << "\n\n\tPlease input the day, the month and the year : \n\n";
cin >> dd >> mm >> yy;
p1 = dd;
p2 = mm;
p3 = yy;
}
// validator here, which works ...
T_sort_data<int,int,int>& operator+=(const T_sort_data<int,int,int>& second)
{
p1+=second.p1;
return *this;
}
friend istream& operator>>(istream& is, T_sort_data& obj) // set function
{
is >> obj.p1;
is >> obj.p2;
is >> obj.p3;
return is;
}
~T_sort_data(){
cout << "\n\t Deconstructed [" << this << "]\n";};
};
int main(){
T_sort_data<int,int,int> * a = new T_sort_data<int,int,int> ;
bool more = true;
string answ;
a->set_date();
//cin >> a; (this doesn't work)
//validator goes here
//a += a; (this, again, doesn't work)
delete a;
return 0;
}
Whenever I make an object using "T_sort_data a;" those operations work fine, but whenever I use "T_sort_data * a = new T_sort_data;"
shit hits the fan.
Can anyone help me with this?
You didn't post exactly what is going wrong so I have to infer that from the code.
The issue that you're running into is that overloaded operators work on instances or references to objects, not on pointers to objects. In the cases where your code doesn't work, you're dealing with pointers to objects. So, in order to use your overloaded operators, you need to dereference the pointer (effectively turning it from a pointer pointing to a value into the value itself) before applying the operator, for example:
cin >> *a;
or
*a += *a;
T_sort_data a is a variable of type T_sort_data.
T_sort_data * a is a variable of type pointer to T_sort_data.
Your overloaded operators expect their operands to be of type T_sort_data, not pointer to T_sort_data. Use the unary * operator to dereference the pointers, so that the operand types are what the operators expect.
This is pretty fundamental. Here's the same thing with int and std::cout: http://codepad.org/N07Xckdy

Operator Overloading = Negation not working as intended

So I'm working with operator overloading and just realized that my negation operator isn't working as it should be. I'm not exactly sure what I've done wrong.
The .h signature
Vector & Vector::operator-()
The .cpp implementation
Vector & Vector::operator-()
{
pVec[0] = -pVec[0];
pVec[1] = -pVec[1];
pVec[2] = -pVec[2];
return *this;
};
Calling:
cout << "-Vector E = " << -VecE << (-VecE).Magnitude() << endl << endl;
The variables in VecE are like [0, 1 , 1] which means when this is called it should display them as [0, -1, -1] but it's not. So what am I missing?
EDIT: Adding copy constructor and iostream<< overload code:
Vector::Vector(const Vector & Copy)
{
pVec = new double[3];
if (0 == pVec)
{
exit(1);
}
else
{
pVec[0] = Copy.pVec[0];
pVec[1] = Copy.pVec[1];
pVec[2] = Copy.pVec[2];
}
};
ostream & operator<<(ostream & Out, Vector & RHS)
{
cout.precision(1);
Out << fixed << "[ " << RHS.pVec[0] << " " << RHS.pVec[1] << " " << RHS.pVec[2] << " ]" << resetiosflags (ios_base::fixed);
return Out;
};
You need to return a copy of the vector. The way this is written, the expression -VecE will actually modify VecE! Since you evaluate -VecE twice, you are negating the vector twice, and (of course) the negation of the negation is the original value.
To implement this change, you need to alter the operator-() declaration to return a Vector instead of a Vector &.
For example:
Vector Vector::operator-()
{
Vector copy(*this);
copy.pVec[0] = -copy.pVec[0];
copy.pVec[1] = -copy.pVec[1];
copy.pVec[2] = -copy.pVec[2];
return copy;
};
cdhowie is right. You are negating twice.
That said, I don't think you need to change the implementation.
Vector const NegVecE = -VecE;
cout << "-Vector E = " << NegVecE << NegVecE.Magnitude() << endl << endl;
EDIT: As PiotrNycz notes, though this will work, the end state is un-intuitive and therefore the correct solution is to return a copy.
{
int i = 3;
int j = -i; //you would expect i to still be 3 here
}

operator << : std::cout << i << (i << 1);

I use the stream operator << and the bit shifting operator << in one line.
I am a bit confused, why does code A) not produce the same output than code B)?
A)
int i = 4;
std::cout << i << " " << (i << 1) << std::endl; //4 8
B)
myint m = 4;
std::cout << m << " " << (m << 1) << std::endl; //8 8
class myint:
class myint {
int i;
public:
myint(int ii) {
i = ii;
}
inline myint operator <<(int n){
i = i << n;
return *this;
}
inline operator int(){
return i;
}
};
thanks in advance
Oops
Your second example is undefined behavior.
You have defined the << operator on your myint class as if it were actually <<=. When you execute i << 1, the value in i is not modified, but when you execute m << 1, the value in m is modified.
In C++, it is undefined behavior to both read and write (or write more than once) to a variable without an intervening sequence point, which function calls and operators are not, with respect to their arguments. It is nondeterministic whether the code
std::cout << m << " " << (m << 1) << std::endl;
will output the first m before or after m is updated by m << 1. In fact, your code may do something totally bizarre, or crash. Undefined behavior can lead to literally anything, so avoid it.
One of the proper ways to define the << operator for myint is:
myint operator<< (int n) const
{
return myint(this->i << n);
}
(the this-> is not strictly necessary, just my style when I overload operators)
Because int << X returns a new int. myint << X modifies the current myint. Your myint << operator should be fixed to do the former.
The reason you're getting 8 for the first is that apparently m << 1 is called first in your implementation. The implementation is free to do them in any order.
Your << operator is in fact a <<= operator. If you replace the line with
std::cout << i << " " << (i <<= 1) << std::endl; //8 8
you should get 8 8.
since m is a myInt your second example could be rewritten as:
std::cout << m << " " << (m.operator<<( 1)) << std::endl;
The order of evaluation for the subexpressions m and (m.operator<<( 1)) is unspecified, so there's no saying which "m" you'll get for the 1'st expression that m is used in (which is a simple m expression). So you might get a result of "4 8" or you might get "8 8".
Note that the statement doesn't result in undefined behavior because there are sequence points (at least one function call) between when m is modified and when it's 'read'. But the order of evaluation of the subexpressions is unspecified, so while the compiler has to produce a result (it can't crash - at least not legitimately), there's no saying which of the two possible results it should produce.
So the statement is about as useful as one that has undefined behavior, which is to say it's not very useful.
Well (m << 1) is evaluated before m and therefore m holds 8 already, as in your operator<< you overwrite your own value.
This is wrong behaviour on your side, the operator<< should be const and not change your object.
Because the << operator of myint modifies its lhs. So after evaluating m << 1, m will actually have the value 8 (while i << 1 only returns 8, but does not make i equal to 8). Since it is not specified whether m<<1 executes before cout << m (because it's not specified in which order the arguments of a function or operator are evaluated), it is not specified whether the output will be 8 8 or 4 8.
The C++ language does not define the order of evaluation of operators. It only defines their associativity.
Since your results depend on when the operator<< function is evaluated within the expression, the results are undefined.
Algebraic operator $ functions should always be const and return a new object:
inline myint operator <<(int n) const { // ensure that "this" doesn't change
return i << n; // implicit conversion: call myint::myint(int)
}