Overloading string with cout operator - c++

I'm trying to overload the << when it receives a string. I want that if the string is lets say Mark, it prints instead Dog. I know it doesn't make sense for you but this is what I need.
I've tried this but it does not work.
std::ostream& operator << (std::ostream &out, string& a);
std::ostream& operator << (std::ostream &out, string& a){
std::cout << "I love dogs";
return out;
}
int main(){
std::cout<<"I love cats";
return 0;
}
I want it to change every single string no matter where I use the function std::cout << string and for it to instead printing what String is, it would always print Dog instead.
My problem is that instead of printing Dog, it keeps on printing the string given. Like it keeps printing I love cats instead of I love dogs
I already tried:
std::ostream& operator << (std::ostream &out, const char* a){
std::cout << "I love dogs";
return out;
}
Instead but it give me segmentation fault.
std::ostream& operator << (std::ostream &out, const char* &a);
And this one keeps on printing I love cats

You have to ensure that your custom operator<< will call the default operator and not call itself. You can do this by using a namespace qualifier on the overloaded operator (std::operator<<). Also, string literals are const char [] and not std::string.
#include <iostream>
std::ostream &operator<<(std::ostream &os, const char *) {
return std::operator<<(os, "I love dogs\n");
}
int main() {
std::cout << "I love cats\n";
}

You should embrace your code with a namespace std for a properly defined operator<<(...) method for iostream.
#include <iostream>
namespace std {
std::ostream &operator<<(std::ostream &os, const char *) {
return std::operator<<(os, "I love dogs\n");
}
}
int main() {
std::cout << "I love cats\n";
}

Related

Global overload of operator<< does not work, why?

I have learnt the operator<< can be overloaded by making it a friend function of class.
For example,
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
friend std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
};
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}
one
two
This seems to work as expected.
But, I'm unable to understand why the same isn't working for a global overload.
#include <iostream>
#include <ostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
stackoverflowstackoverflow
Expected the strings to be separated by a newline, but didn't work as expected.
Your operator using
std::cout << "stackoverflow";
requires a user-defined conversion from an object of the type const char * (after the implicit conversion of the string literal to pointer to its first character) to an object of the type std::string.
However the standard basic_ostream class has already an operator that does not require such a conversion
template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
So this operator is called instead of your operator.
Moreover within your operator
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
there is recursive calls of itself.
Your could define your operator the following way
#include <iostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const char *s)
{
return std::operator <<( os, s ) << '\n';
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
and get the expected result
stackoverflow
stackoverflow
Note that "stackoverflow" is of type const char[], but not std::string. That means your overload won't be invoked, but the one from standard library (operator<<(std::basic_ostream) is invoked, because it's an exact match and doesn't require the implicit conversion from const char[] to std::string.
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
BTW: It could be found because of ADL.
You can overload globally, but "stackoverflow" is not a std::string, so yours isn't used.
(And there already is such an overload in the standard library.)
To see that it works, move your first overload out of the class definition and make it a non-friend.
The only reason it has to be declared friend is that you have declared it inside the class definition, so it would be a member function otherwise.
This will work as you expect:
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
};
std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}

Dealing with operator overload method as a friend

I tried to create simple class and to overload some of it's operators, however, i failed at the very beginning, here's my code:
#include <iostream>
class Person
{
char *firstName;
char *lastName;
int age;
friend std::ostream &operator<<(std::ostream &, const Person &);
public:
Person() : firstName("Piotr"), lastName("Tchaikovsky"), age(10) {}
Person(char* f, char* l, int a)
{
this->firstName = f;
this->lastName = l;
age = a;
}
std::ostream &operator<<(std::ostream& out, const Person &p)
{
out << p.firstName << " " << p.lastName;
return out;
}
};
int main()
{
Person a;
getchar();
getchar();
}
So, before i created this operator overloading function i used debugger to see if constructor is going to work, and it worked, since default values were given correctly to the variable a i created, after that, all i did was that i created function that overloads the operator << and it is a friend function of my class, since i am taught that it is a good thing to do due to the type of the first parameter of overloading function, however, when i try to run this (NOTE: i have not tried to print out anything yet, i wanted to check if everything works fine first) it gives me errors saying:
"too many parameters for this operator function",
"binary 'operator <<' has too many parameters" and
" 'Person::operator<<' :error in function declaration; skipping function body"
however, i can't find any problems with function declaration, and i cannot possibly see how two parameters can be too many for this function. Any help appreciated!
You declare the friend function as a global non-member function. Then you define a member function.
Move the definition of the operator<< function to outside the class:
class Person
{
...
friend std::ostream &operator<<(std::ostream &, const Person &);
...
};
std::ostream &operator<<(std::ostream& out, const Person &p)
{
out << p.firstName << " " << p.lastName;
return out;
}
Or alternatively define the friend function inline:
class Person
{
...
friend std::ostream &operator<<(std::ostream &, const Person &)
{
out << p.firstName << " " << p.lastName;
return out;
}
...
};

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.

How does the << Operator exactly work?

I have some problems in understanding the << operator.
If I have:
#include <iostream>
using namespace std;
//...
int t = 5;
cout << "test is: " << t << endl;
Now the function operator<< is called.
ostream& operator<<(ostream& out, string* s)
{
return out << s << endl;
}
ostream& operator<<(ostream& out, int* value)
{
return out << value << endl;
}
the string-pointer points to the address with value test is: but to what does the element out refer (to cout?)? and is the function body of ostream& correct in that way?
Thank you so much for any explanation.
First, let's fix your code: the operators should be taking const references or values instead of pointers:
ostream& operator<<(ostream& out, const string& s) // const reference
ostream& operator<<(ostream& out, int i) // value
Now to your question: you are correct, the out parameter receives the reference to the cout, or whatever is the ostream& returned from the expression on the left side of <<. The expression on the left of << is not necessarily cout, though - other common cases are results of other << operators* for chaining, and stream manipulators. In all cases these expressions return a reference to ostream so that the "chain" could continue.
* The reason the operator<< return an ostream& is so that you could chain the output. In overwhelming number of cases you wold return the same ostream& that you receive as the first parameter, although there is no limitation on the part of the standard C++ library requiring you to do that.
int t = 5;
cout << "test is: " << t << endl;
First call would be to:-
ostream& operator<<(ostream& out, const char* str)
out = cout
str = "test is: "
Second call would be applied on object returned by first call which is ostream.
ostream& operator<<(ostream& out, int x)
out = cout
x = t
This is not true. It's int not int*, and char const* not string*.
out, of course, refers to std::cout in this example. What else would it be?
And no those bodies are not correct in the slightest — they attempt to reinvoke themselves infinitely, and do nothing else.

Overloading I/O operator C++

I'm trying to overload the << operator. I'm expecting the output to be InitializingHello WorldOut but it is just outputting Hello World. I can't figure out what is wrong with my code. Thanks for your help.
#include <iostream>
using namespace std;
ostream &operator << (ostream &out, const char* &s)
{
out << "Initializing" << s << "Out";
return out;
}
void main() {
cout << "Hello World" << endl;
system("Pause");
}
"Hello World" is actually of type const char[12], which can decay into an r-value (temporary) of type const char *, but your function takes a reference to a const char*, and as you may know, you cannot bind a reference to a non-const r-value. So your operator is not called, but instead the standard ostream &operator << (ostream &out, const char* s) is.
PS. Please do not write void main(). It should be int main() unless you are in an embedded system (not likely).
There already is an overload for << with the exact same prototype. The compiler cannot decide which to use...
There is already a operator<< for const char* defined in the standard library, which is used in the output. Your overload is not used because the temporary string literal cannot be bound to the non-const reference in the operators second parameter.
If you remove the reference or make it const, then your operator is called. It doesn't even conflict with the one in your standard library, since that one is implemented as a function template. Yours is not, and non-templated functions are preferred by the compiler.
If it is then called, it leads to a stack overflow because out << "Initializing" immediately calls the same operator again recursively.
rodrigo pointed out that the type of a string literal is const char[x], and I had an evil idea:
#include <iostream>
using namespace std;
template<int len>
ostream &operator << (ostream &out, const char (&s)[len])
{
out << ((const char*)"Initializing") << ((const char*)s) << ((const char*)"Out");
return out;
}
int main() {
cout << "Hello World" << endl;
}
http://ideone.com/7wCNy
I think that since the left hand side is in the std namespace, it's using the function ostream& std::operator << (ostream &out, const char* s) that's defined in the std namespace instead of yours in the global namespace. If you were to try to put yours into the std namespace, you'd get a linker error. Your only real hope is to change the types of one side or the other, probably by making a wrapper around them.
struct charptr {
const char* ptr;
charptr(const char* p) :ptr(p) {}
};
ostream &operator << (ostream &out, const charptr &s)
{
out << "Initializing" << s.ptr << "Out";
return out;
}
int main() { //int main, not void
cout << charptr("Hello World") << endl;
system("Pause");
}