void operator<< (const Integer& left, const Integer& right)
{
cout << "\n: " << right.i;
}
can be accessed like:
Integer obj;
obj << 5 << 3 << 2;
Fine:
But qDebug works like qdebug() << 2;
Which means that the left operand of << operator is a function.
What should be the syntax of a user defined function so that I can write:
myfunc() << 2;
The left operand is not a function, it is the value the function returns. Specifically, qDebug() returns an instance of QDebug, which has some 20 overloads of << defined.
Related
I write a class Fraction, and would like to display Fraction object with std::cout:
Fraction f(3, 5);
std::cout << f << std::endl;
I know overloading operator << can be used for this display purpose. But I can also overload operator type() function, and when only with operator double()(let type be double), I can still std::cout << f << std::endl.
Even more, I can also implement operator std::string(). But, when the mentioned 3 overloaded operator functions all exist, without explicitly type conversion, which one is called when doing std::cout << f << std::endl ? This really makes me curious, is this undefined behavior denpending on compiler implementation, or if there is some rule for scoring the closest/most suitable function to call?
To reproduce, use the following code:
#include <iostream>
#include <string>
class Fraction
{
public:
Fraction(int num, int den=1):
numerator(num), denominator(den) {}
operator double() const {
std::cout << "[operator double()]";
return numerator*1.0 / denominator;
}
operator std::string() const {
std::cout << "[operator std::string()]";
return std::to_string(numerator) + "/" + std::to_string(denominator);
}
private:
int numerator;
int denominator;
#ifdef OVERLOAD_STREAM_OP
friend std::ostream& operator << (std::ostream& os, const Fraction& frac);
#endif
};
#ifdef OVERLOAD_STREAM_OP
std::ostream& operator << (std::ostream& os, const Fraction& frac)
{
std::cout << "[operator <<]";
os << std::to_string(frac.numerator) << "/" << std::to_string(frac.denominator);
return os;
}
#endif
int main()
{
Fraction f(3, 5);
double d = 4 + f;
std::cout << "\n--- now let's print\n";
std::cout << "f: " << f << std::endl;
std::cout << "f: " << std::string(f) << std::endl;
std::cout << d << std::endl;
return 0;
}
The output on my ubuntu 20.04:
(base) zz#home% clang++ fraction.cpp
(base) zz#home% ./a.out
[operator double()]
--- now let's print
f: [operator double()]0.6
f: [operator std::string()]3/5
4.6
When writing a non-member function to overload an operator, does the 1st parameter correspond to the left operand and the 2nd parameter to the right operand?
I was trying to overload the "<<" operator to use it like this:
stream << ClassA << ClassB
Below is an example where FeetInches is a class with member variables feet and inches .
Is that why this parameter order works:
ostream &operator<<(ostream &strm, const FeetInches &obj)
{
strm << obj.feet << " feet, " << obj.inches << " inches";
return strm;
}
--
but this parameter order doesn't work?
ostream &operator<<(const FeetInches &obj, ostream &strm)
{
strm << obj.feet << " feet, " << obj.inches << " inches";
return strm;
}
Yes, it all works as you said.
ostream comes 1st as we don't have any invoking object here.
ostream &operator<<(ostream &strm, const FeetInches &obj)
{
strm << obj.feet << " feet, " << obj.inches << " inches";
return strm;
}
as cout<<obj<<endl; will be interpreted as operator<<(cout,obj);.
We know that the fascinating class iostream is something too powerful.
it has overloded the insertion operator "<<" to take many datatypes:
ostream& operator(ostream&, int),
ostream& operator(ostream&, char)...
we cannot instantiaate ostream: ostream print;
because ostream because its most CTORSs are "protected-socoped" (cannot be accessed from outside).
the only Constructor we can call is ostream(streambuf*) which takes a pointer to another class object ( class streambuf);
I just wanted to mess up with this class:
#include <ostream>
using namespace std;
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << x; // normally works well and it prints the address that x points to but instead the program get in infinite loop or crushes!
return *x;
}
int main()
{
system("color 1f");
int* pVal = new int(57);
cout << *pVal << endl;
int* pX = new int(7);
cout << *pX << endl;
cout << *pVal << ", " << *pX << endl;
//cout << pVal << endl; // this doesn't work because my operator returns
//int and not a reference to ostream.
// and it is equal to: 0 << endl; which generates the same error
cout << pVal; // this works
// cout << endl << endl << endl;
return 0;
}
I overloaded the insertion operator to take an lvalue as a reference to an ostream object and a pointer to int as rvalue, I popup a message inside my function to get sure that it is invoked.
Note that I intentionally overloaded it to return int value so that no one can write:
out << pInt << *pInt << endl;
... but just:
out << pInt;
My problem, as you can see in the inline-comments above, is that whilst cout << x normally works well, instead the program get in infinite loop or crushes!
return *x;
Can anyone explain why I am getting the error?
The problem hapens because if you just cout << x, it will call your overloaded function over and over. It never returns.
Here's the solution (cast x to void*)
int operator << (ostream& out, int* x)
{
out << "invoked!" << endl;
cout << *x; // works well!
cout << (void*)x;
return *x;
}
I have an overloaded << operator from my reckful class implemented as follows:
ostream& operator << (ostream& os, const reckful& p)
{
os << p.PrintStuff();
return os;
}
PrintStuff() just being a member function of reckful that returns a string.
The way I understand things, if I were to write something like cout << reckobject << endl; in main(), cout << reckobject would take precedence and my overloaded << (using cout as the left operand and reckobject as the right operand) would return the ostream object os, leaving the expression os << endl; to be evaluated which would output the string and then end the line. So, the first << is the one I declared and the second is the standard << right?
However, my main question is... what is the sequence of events, which are the left and right operands, and which << operators are which when I run a statement like this:
cout << "reckful object = " << reckobject << "!" << endl;
Why does this work if there isn't an ostream object and a reckful object on either side of one << ?
Thanks.
If you notice standard way to implement << it returns the ostream itself. This is the critical piece
So something like
cout << "reckful object = " << reckobject << "!" << endl;
will be called once for
cout << "reckful object = "
This function call will return a ostream with which the second call will be made
namely
cout << reckobject;
so on an so forth.
You can test is out by implementing your << as
void operator << (ostream& os, const reckful& p)
{
os << 1;
}
in which case you can do
std::cout << p;
but not
std::cout << p << std::endl;
The operators make it harder to understand but consider this Point class
struct Point
{
Point& setX( int x) { X = x; return *this;}
Point& setY( int y) { Y = y; return *this;}
int X;
int Y;
};
The way setX and setY are defined, allows
Point p;
p.setX( 2 ).setY( 4 );
This is the same mechanism << is using to chain function calls.
Because each << returns a reference to cout. Because the operator << is left-associative, the calls are done from left to right, so
a << b << c
is equivalent to
(a << b) << c
which is equivalent1 to
operator<<(operator<<(a, b), c);
So in your example, you are doing
operator<<(operator<<(operator<<(operator<<(cout, "reckful object = "), reckobject), "!"), endl);
As you can see, each << depends on the return value of the previous << (or just cout in case there is no further left <<). If you change one of the return types of the <<s to void, you effectively stop any more << calls, because void can't be used as an argument to a function.
1 It's not exactly equivalent because in that example, all operator<< are free functions, whereas in reality, some can be member functions, so you could have a mix of member and non-member calls like
operator<<(a, b).operator<<(c);
or
operator<<(a.operator<<(b), c);
class A
{
public:
ostream& operator<<(int string)
{
cout << "In Overloaded function1\n";
cout << string << endl;
}
};
main()
{
int temp1 = 5;
char str = 'c';
float p= 2.22;
A a;
(a<<temp1);
(a<<str);
(a<<p);
(a<<"value of p=" << 5);
}
I want the output to be: value of p=5
What changes should is do...and the function should accept all data type that is passed
There are 2 solutions.
First solution is to make it a template.
template <typename T>
ostream& operator<<(const T& input) const
{
cout << "In Overloaded function1\n";
return (cout << input << endl);
}
However, this will make the a << str and a << p print c and 2.22, which is different from your original code. that output 99 and 2.
The second solution is simply add an overloaded function for const char*:
ostream& operator<<(int string)
{
cout << "In Overloaded function1\n";
return (cout << string << endl);
}
ostream& operator<<(const char* string)
{
cout << "In Overloaded function1\n";
return (cout << string << endl);
}
This allows C strings and everything convertible to int to be A <<'ed, but that's all — it won't "accept all data type that is passed".
BTW, you have forgotten to return the ostream.