Getting the compiler to perceive << as defined for a specific class - c++

I edited a post of mine with this question, yet got no answers.
I overloaded << for a class, Score (defined in score.h), in score.cpp.
ostream& operator<< (ostream & os, const Score & right)
{
os << right.getPoints() << " " << right.scoreGetName();
return os;
}
(getPoints fetches an int attribute, getName a string one)
I get this compiling error for a test in main(), contained in main.cpp
binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion)
How come the compiler doesn't 'recognize' that overload as valid? (includes are proper)
Thanks for your time.
EDIT:
As requested, code causing the error:
cout << ":::::\n" << jogador.getScore() << endl;
jogador is a Player object, which contains a Score one. getScore returns that attribute.

Perhaps you didn't declare your operator<< in score.h? It should normally contain something like:
ostream& operator<< (ostream & os, const Score & right);
Edit: More accurately, that should be:
std::ostream &operator<<(std::ostream &os, const Score &right);
You definitely should not have a using namespace std; in a header, so you need the std:: for it to work correctly.

Try declaring operator<< as a friend function in your class:
struct Score
{
friend ostream& operator<<(ostream& output, const Score& right);
};
This will allow your Score structure to fit nicely into printing statements:
Score my_score;
cout << my_score << endl;
When in doubt, check the C++ FAQ.

Related

Friend function defining an ostream operator

I would like to define an ostream operator to let me easily output variables of type alglib::complex. To provide a working example without including the alglib library I'll instead overload the output of complex<double> below (this clarification because of an earlier version of the question). In the header file "my_class.h" I have
using namespace std;
#include <complex>
#include <iostream>
class my_class {
public:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
void output(complex<double>);
my_class() {}
~my_class() {}
};
And in the source file "my_class.cpp" I have
#include "my_class.h"
void my_class::output(complex<double> cd) {
cout << cd << endl;
}
Finally I have a main method file "run_my_class.cpp":
#include "my_class.h"
int main(int argc, const char* argv[]) {
my_class obj;
complex<double> cd=complex<double>(1.0,-1.0);
obj.output(cd);
}
I try to compile using
g++ -c my_class.cpp
but this gives me the error
my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument
ostream& operator << (std::ostream& os, complex<double> a) {
However, if I define the operator as a friend, namely friend ostream& operator << (std::ostream& os, complex<double> a), it compiles and I compile the main method:
g++ run_my_class.cpp my_class.o -o run_my_class
And it works as it should. However this is not what it seems the friend keyword is for. Is there a better way to make this work?
Since operator << will be called on an std::ostream, you cannot define this procedure as a member function for my_class, you have to define it as a global function, since it's an operation for std::ostream, not my_class.
By putting the friend keyword into the declaration, you are saying that you want to declare the operator << as a friend global function (not a member function!). The C++ standard lets you put the definition of the friend function there, but it won't be a member function. It is the same as the following, which is more clear:
#include <complex>
#include <iostream>
class my_class {
public:
friend ostream& operator << (std::ostream& os, complex<double> a);
void output(complex<double>);
my_class() {}
~my_class() {}
};
std::ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
As it was already pointed out in the comments, the usage of friend is not necessary here.
Irrelevant to the question, but please be aware that resolving namespaces in a header file is generally a really-really bad idea, since all other files including it will implicitly resolve that namespace too. It can easily lead to vexing compilation errors in the long run.
I wouldn't call it a better way but a more clear way.
Here's your stream operator again:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
Its first parameter is the output stream. Since you do not have access to the output stream, you can't use the output stream operator as a member function unless you make it a friend of the class.
If you want to want to avoid using friend you can always define it as a function external to the class, and that is the most common way.

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.

Cannot access private member declared in class

I am working with operator overloads for the first time and am setting up the overload for the extraction operator (<<). I'm stuck in one of two errors that are preventing me from continuing. The code is as follows:
ostream &operator << (ostream &output, const Distance &d1)
{
if (d1.miles > 0)
{
output << d1.miles << "m ";
}
if (d1.yards > 0)
{
output << d1.yards << "y ";
}
if (d1.feet > 0)
{
output << d1.feet << "\' ";
}
output << d1.inches << "\"";
return (output);
}
The overload is declared as a friend in the header file as follows:
friend ostream &operator<< (ostream output, const Distance &d1);
The first issue I encounter is that when the overload is formatted this way (which is as far as I can tell, the correct way) it does not allow me to access the miles, yards, feet, or inches member data, despite the function being set as a friend in the header file.
If I change the overload to read :
ostream &operator << (ostream output, const Distance &d1)
{
if (d1.miles > 0)
{
output << d1.miles << "m ";
}
if (d1.yards > 0)
{
output << d1.yards << "y ";
}
if (d1.feet > 0)
{
output << d1.feet << "\' ";
}
output << d1.inches << "\"";
return (output);
}
Then the overload works correctly, but it does not work in my main function as it returns the error:
error C2248: 'std::basic_ostream<_Elem,_Traits>::basic_ostream' : cannot access private member declared in class 'std::basic_ostream<_Elem,_Traits>'
for every instance of cout in the function. Plus, the previous examples I have show that this would be incorrect. What am I doing wrong in the first code example that is preventing me from accessing the private member data? I've looked at several other instances of this being asked on various sites, but nothing quite matches what I am getting. I have tried compiling with Visual Studio Express 2012 and g++, both return the error.
The declaration inside the class definition should be:
friend ostream &operator<< (ostream &output, const Distance &d1);
// ^--- important
The error in your first attempt is because when you write a function ostream &operator<< (ostream &output, const Distance &d1), this is not the same function you friended because it has different arguments.
The second attempt should have various errors , as it is not permitted to pass ostream by value.

How to get THIS when overloading operator in C++

I'm a student learning c++. today, I was making a operator overload function to use it in 'cout'. following is a class that contains name, coordinates, etc.
class Custom {
public:
string name;
int x;
int y;
Custom(string _name, int x, int y):name(_name){
this->x = x;
this->y = y;
}
int getDis() const {
return static_cast<int>(sqrt(x*x+y*y));
}
friend ostream& operator << (ostream& os, const Custom& other);
};
ostream& operator << (ostream& os, const Custom& other){
cout << this->name << " : " << getDis() << endl;; // error
return os;
}
However, this code isn't working because of 'THIS' keyword that I was expecting it points to the object. I want to show the object's name and distance value. How can I solve it? I think it is similar with Java's toString method so that it will be able to get THIS.
Thanks in advance for your answer and sorry for poor english. If you don't understand my question don't hesitate to make a comment.
this is available only in member functions, but your operator<< is not a class member (declaring it as friend does not make it a member). It is a global function, as it should be. In a global function, just use the arguments you are passing in:
ostream& operator << (ostream& os, const Custom& other)
{
os << other.name << " : " << other.getDis() << endl;
return os;
}
Also note os replaced cout in the code above. Using cout was an error - the output operator should output to the provided stream, not to cout always.

Can operator<< in derived class call another operator<< in base class in c++?

In my code, Manager is derived from Employee and each of them have an operator<< override.
class Employee{
protected:
int salary;
int rank;
public:
int getSalary()const{return salary;}
int getRank()const{return rank;}
Employee(int s, int r):salary(s), rank(r){};
};
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
class Manager: public Employee{
public:
Manager(int s, int r): Employee(s, r){};
};
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << (Employee)m << endl; //can not compile, how to call function of Employee?
return out;
}
I hoped cout << (Employee)m << endl; would call ostream& operator<< (ostream& out, Employee& e), but it failed.
Cast to a reference instead of a copy:
cout << (Employee&)m << endl; //can not compile, how to call function of Employee?
Also note the ostream operator is in no way member of the class(it seems you are confused about that from the title of the question).
Change cout << (Employee)m << endl; to cout << (Employee&)m << endl;.
The explanation of the error message is this:
When you attempt the cast (Employee)m, you are creating a temporary. The operator<< overload takes a reference. You cannot take a reference to a temporary.
Since you really just want it to print it's own data (not make a copy of itself), you cast the reference you have to the reference of the type you need (it's base class).
As jrok pointed out in his answer, you can also accomplish this by providing a virtual function to print the data. That would be a simpler approach as it would not require you to overload operator<< for every derived class.
The usual way of doing this is to have (a possibly private or protected) virtual print (or any other suitable name) function in the base class that derived classes can override.
You only provide general operator<< for a reference to the base class and call print inside it. The overriding print functions can call the base's print, if need be.
Your overload:
ostream& operator<< (ostream& out, Employee& e)
only works for references to Employee objects, so it won't work on non-reference values (like the result of a cast).
Normally, the prototype would be:
ostream& operator<< (ostream& out, const Employee& e)
which also provides the reassurance that printing an Employee doesn't mutate it. If you change that, things should work just fine. (ostream& does have to be a reference, not a const reference, because the ostream is mutated by the print operation.)
There are two problems which combined make your compilation to fail.
(1) This declaration and definition:
ostream& operator<< (ostream& out, Employee& e){
out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
return out;
}
Despite you don't change e, you take it reference to non-const. This forbids you calling this operator on an rvalue.
(2) This line
cout << (Employee)m << endl;
As said by others you are slicing m. In addition, the cast (Employee) m returns a temporary Employee which is an rvalue.
In summary, the cast (Employee)m yields an rvalue which cannot bind to e.
You can fix either one or the other to make your code compiler but it's better to fix both problems to make your code more robust:
// ...
ostream& operator<< (ostream& out, const Employee& e) {
// ...
// ...
cout << static_cast<Employee&>(m) << endl;
// ...
First, you overload a global function. This is another concept than overriding. see Override and overload in C++
Next, your cast is wrong. This should do:
ostream& operator<< (ostream& out, Manager& m){
out << "Manager: ";
cout << static_cast<Employee&>(m) << endl; //can not compile, [...]?
return out;
}
...if you really want to overload the global << operator.