Stream overloading in C++ - c++

why does
void operator<<(ostream out, Test &t);
return an error whereas
void operator<<(ostream &out, Test &t);
does not ?

Because you cannot copy streams, you have to pass them per reference.
Note that the canonical form of operator<< is this:
std::ostream& operator<<(std::ostream& out, const Test &t)
{
// write t into out
return out;
}
returning the stream is important so that you can string output together:
std::cout << Test() << '\n';

Related

c++ overload "<<" doesn't work for output "obja + objb"

I overload "<<" and "+" operators for my class. It works fine if I output single object using cout<<a;. But it fails when I output cout<<a+b;
g++ version: g++ (GCC) 9.2.0
class UTF8string{
private:
string data;
public:
UTF8string();
UTF8string(string a);
int bytes();
int find(string a);
int length();
void replace(string a, string b);
UTF8string operator+(UTF8string &a);
UTF8string operator*(int a);
UTF8string operator+=(const UTF8string& rhs){
data.append(rhs.data);
return *this;
}
friend UTF8string operator!(UTF8string &a);
friend std::ostream& operator<<(std::ostream& os, UTF8string &a);
friend UTF8string operator+(int a, UTF8string &other );
};
std::ostream& operator<<(std::ostream& os, UTF8string &a){
os << a.data;
return os;
}
UTF8string UTF8string::operator+(UTF8string &a){
string b = data ;
return UTF8string(b.append(a.data));
}
my test code:
cout << "test + test2: " << test + test2 << endl; // doesn't work
cout << "test contains: " << test << endl; // works well
Error
testUTF8string.cpp:38:38: 错误:cannot bind non-const lvalue reference of type ‘UTF8string&’ to an rvalue of type ‘UTF8string’
38 | cout << "test + test2: " << test + test2 << endl;
| ~~~~~^~~~~~~
You're using references-to-non-const throughout.
That is a bad idea.
If you don't need to modify the object through a reference, the reference should be to const.
If your reference is not to const, temporaries cannot bind to it.
The return-by-value result of your operator+ is a temporary.
Result of your overloaded operator+ in test + test2 is temporary value. Temporary value cannot be passed to function by non-const reference.
It can be fixed by using const reference:
std::ostream& operator<<(std::ostream& os, const UTF8string &a){
os << a.data;
return os;
}
UTF8string UTF8string::operator+(const UTF8string &a){
string b = data ;
return UTF8string(b.append(a.data));
}
It is good practice to always use const references when passing arguments which are meant to be read-only.
Apart from the solution what #Lightness Races with Monica have suggested you can also overload the operator << for rvalue references like:-
friend std::ostream& operator<<(std::ostream& os, const UTF8string &&a);
It is sometimes useful to overload like this when moving is cheaper then copying.
Or for some reason you want a different implementation in two cases.
NOTE: In case of operator << it doesn't make sense to do the oveloading as the data/object being passed to stream should be const

Return type ostream for derived class

With inheritance, I'm trying to create an overloaded output operator in my base class that calls an output function in the proper derived class to print the correct data based on which type of object.
How do you return an output that can be sent into an overloaded output operator so you can output the object with just cout << object << endl;
For instance:
ostream & operator<< (ostream &out, const person &rhs){
out << rhs.print_data();
return out;
}
ostream student::print_data(){
ostream out;
out << data;
return out;
}
ostream faculty::print_data(){
ostream out;
out << data;
return out;
}
EDIT: I'm trying to figure out if I need to return type ostream or ostream & in the print functions
Streams can not be copied, so if you want to return (or pass as argument) it must be done by reference. And you can't return a reference to a local variable (as those will go out of scope and "disappear").
Besides, a basic std::ostream object doesn't make sense to create instances of.
Simple solution: Pass the stream as argument (by reference of course) to the functions:
ostream& operator<< (ostream &out, const person &rhs){
return rhs.print_data(out); // No need for any output here
}
ostream& student::print_data(ostream& out){
return out << data;
}

C++ How do I print an object?

I have created a constructor
Location(double xIn,double yIn,string placeIn,int timeIn)
: x(xIn),y(yIn) ...so on {
Say I want to print Location home(x,y,place,time); that's in the main().
How would I do so? I've been searching around and was told to use operator<<. How would I implement this?
UPDATE: After creating some get methods and I tried doing,can't exactly compile it because of the problem
ostream &operator<<(ostream & o, const Location & rhs){
o << rhs.getX() << "," << rhs.getY() << "," << rhs.getPlace() << "," << rhs.getTime();
return o; }
Here is the stencil for overloading operator<<:
class Any
{
public:
friend std::ostream& operator<<(std::ostream& output, const Any& a);
private:
int member;
};
std::ostream&
operator<<(std::ostream& output, const Any& a)
{
output << a.member;
return output;
}
This one possible stencil, there are other possibilities. Search the internet for "c++ stream insertion operator overload example" for other implementations.

no return statement in friend class

The warning is being generated by the ostream & operator<<(ostream &os, A &A0) function.
Here's how the class's defined:
class A
{
public:
friend ostream & operator<<(ostream &os, A &A0);
A& operator=(string strSlot_);
A& operator+(string strSlot_);
A& operator+(const A &B);
A& operator=(const A &B);
string slotReturn();
A(string strSlot_);
A(const A &object);
void slotChange();
void sCout();
~A();
A();
private:
string strSlot;
int n;
};
ostream & operator<<(ostream &os, A &A0)
{
os << "strSlot = \"" << A0.slotReturn() << "\"" << endl;
}
string A::slotReturn()
{
return strSlot;
}
The question is, what is it supposed to return? *this doesn't seem to work (because it's a friend?). (It's merely a warning, but still, I just want to know.)
Also, why can't I pass A &A0 as a const (in which case the error is: "passing 'const A' as 'this' argument of 'std::string A::slotReturn()' discards qualifiers")?
You need to return the std::ostream& itself:
ostream & operator<<(ostream &os, A &A0)
{
return os << "strSlot = \"" << A0.slotReturn() << "\"" << endl;
}
As an aside, the terminology is slightly off. There is no "friend class". The std::ostream& operator<< is the friend here. But it doesn't even need to be a friend, because it just calls a public member function of A. So you can remove the friend declaration.
You should probably also make slotReturn() a const method:
string slotReturn() const;
// ^ const method
and modify the ostream& operator<< to take a const reference:
ostream & operator<<(ostream& os, const A& A0) { .... }
This will allow you to print out temporaries:
std::cout << A("I am a temporary!") << "\n";

simple c++ operator overloading help

How do I overload the << operator? From the error I am getting, it seems that std::cout doesn't know how to use <<.
This is in a class:
// uint64_t UPPER, LOWER;
std::ostream & operator<<(std::ostream & stream){
if (UPPER)
stream << UPPER;
stream << LOWER;
return stream;
}
I am getting error: no match for 'operator<<' in 'std::cout << test' which doesn't seem to make sense.
edit:
Neither this:
std::ostream & operator<<(std::ostream & stream, uint128_t const & val){
if (val.upper())
stream << val.upper();
stream << val.lower();
return stream;
}
nor this:
std::ostream & operator<<(std::ostream & stream, uint128_t val){
if (val.upper())
stream << val.upper();
stream << val.lower();
return stream;
}
is changing the error.
The << operator takes two arguments, a left hand side, and a right hand side. Therefore you have to define the function with two parameters:
std::ostream operator<<(std::ostream &os, const MyClass &obj);
And you have to define it outside of your class definition, as far as I can remember. Inside of the class definition you can only have operators that take that class as the left hand side.
You typically want the operator<<() overload to be a 'free function' (outside of your class) so it can bind to the stream naturally:
// this is outside your class definition
std::ostream& operator<<(std::ostream& os, const myclass& rhs)
{
// whatever...
return os;
}
Then inside your class you declare it a friend if necessary so it can get to the class internals:
friend std::ostream& operator<<(std::ostream& os, const myclass& rhs);
An alternative to having this be a friend (which some people consider to be breaking encapsulation) is to have a public function in your class that will output itself to a stream and call that in your operator<<() overload:
// inside class myclass - a normal public member function
std::ostream& dump( std::ostream& os)
{
os << some_class_member;
// ...
return os;
}
// now, the `operator<<()` overload doesn't need to be a friend
// this is still outside your class definition
std::ostream& operator<<(std::ostream& os, const myclass& rhs)
{
return rhs.dump(os);
}
operator<< outside a class requires two arguments:
std::ostream& operator<<(std::ostream& stream, type_you_want_output const& thing)