Why is my overloaded << operator not working? - c++

I'm trying to understand how to properly overload the "<<" operator so that I can use
std::cout << my_object;
to print useful debug messages. In particular, I need to have an implementation of << for each of my subclasses, so I'm declaring << to be virtual in the superclass.
Right now I'm stuck with the following piece of code
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() { };
virtual ostream& operator<<(std::ostream &strm) = 0;
};
class Square : public Shape {
int size;
public:
Square() { size = 10; }
~Square() { }
ostream& operator<<(std::ostream &strm) {
return strm << "a square with size " << size;
}
};
int main() {
Square *my_square = new Square();
cout << "my_square is " << my_square << "\n";
}
which (I think) should be working, but doesn't. What I get when using "<<" is that the pointer value of my_square gets printed, rather than the result of the overloaded << .
$ ./a.out
my_square is 0xcacc20
What am I missing here?

operator<< can't be a member function. This is because of the order of the arguments. The stream has to come first.
When calling an overloaded operator, such as:
os << object;
the compiler will attempt to look up both
os.operator<<(object);
and
operator<<(os, object);
(The rules for this can be rather complex, I won't attempt to describe them here.)
Because the stream always comes on the left, your member function will never be found, since it would have to be called as:
object.operator<<(os);
You need to write a free function like:
ostream& operator<<(std::ostream &strm, Square const& square) {
return strm << "a square with size " << square.size();
}
(where Square::size() returns the size member).
Then you need to remember to dereference your pointer too:
std::cout << *my_square << '\n';
Although I see no reason to be dynamically allocating my_square in this example anyway. Just stick it on the stack as a local variable.
If the aim here is ultimately to be able to print any Shape&, and have the printed output follow the "real" type, you would need to create:
virtual std::ostream& print(std::ostream&) const = 0;
in the Shape base class, and override it in each derived class, then have a free function:
std::ostream& operator<<(std::ostream& os, Shape const& shape)
{
return shape.print(os);
}
It is often advised to make all binary operators on your type non-member functions, so that both arguments are treated equally, and the operation remains commutative. See Scott Meyers, Effective C++ (3rd Edition), Item 24, (or find a summary online).

As noted by others, the problem is that operator << can't be member function (because of the order of arguments). The canonical way to do this is to have operator <<(const Shape&) call a virtual function in Shape
class Shape {
friend ostream& operator<<(std::ostream& str, const Shape& shape);
virtual void do_print(ostream& str) = 0;
public:
virtual ~Shape() { };
};
ostream& operator<<(std::ostream& str, const Shape& shape) {
shape.do_print(str);
return str;
}
Note that it is legal to have do_print be private, even though it is going to be (must be) overridden by derived classes. You could make it protected though if you like.

What am I missing here?
You have created operator which will get you class as a first argument and stream as the second.
my_square << std::cout;
I'd create free function and to make it dynamic I'd call some virtual method in it

Related

What is the correct way to create a function that takes an ostream reference and prints to it?

As the title states, I am trying to make a function that takes an ostream reference and prints to it. The context is that of a Binary Search Tree.
I am not too experienced with ostream, I've only used it once before (only started learning c++ about 3 weeks ago) which I based off a basic template example for operator<< overloading that I found on google.
With my limited understanding I am not sure how I would implement this with a function that I have created.
This is what I've attempted so far based on my limited knowledge,
I first created the reference void write(std::ostream &out) const;
Then I tried to create the function,
std::ostream& write(std::ostream &out,node& o){
out << o.leftChild<< " " << o.val << " " << o.rightChild;
return out;
}
i.e. o.leftChild and o.rightChild should print the results of the node. o.val is just the data in the node.
The expected results should be something like 1 2 3 4. However, if I attempt to use the reference as I did above, I am given an error message by my IDE saying that write was not implemented.
However if I wrote the reference as a method, the results are returned as blank.
UPDATE: Removed what I assumed was the reference, and I no longer get any error messages.
However result is still zero, which I assume is because of my incorrect implementation.
UPDATE2:
What I am trying to attempt precisely, is to have the write function print to it,
The result of calling write on the left child, followed by a space, data from the node, a space and the the result of calling write on the right child (if there is one).
All prior code to this segment I've shown works as intended. For the variables, data is a template argument type (T), the left and right childs are unique_ptr<node>s.
Your first write() declaration is declaring a method in a class (presumably the node class), but you are not implementing the body of that method. That is what the compiler is complaining about.
Your second write() is implementing the body of a standalone function, not the class method.
Try something more like this instead:
class node {
...
public:
...
void write(std::ostream &out) const;
};
void node::write(std::ostream &out) const {
if (leftChild) {
leftChild->write(out);
out << " ";
}
out << val;
if (rightChild) {
out << " ";
rightChild->write(out);
}
}
Which can then be used like this:
node n;
...
n.write(std::cout);
unique_ptr<node> n(...);
...
n->write(std::cout);
If you want to implement a standalone function, it would look more like this:
class node {
...
public:
...
void write(std::ostream &out) const;
};
std::ostream& write(std::ostream &out, const node &n);
void node::write(std::ostream &out) const {
...
}
std::ostream& write(std::ostream &out, const node &n) {
n.write(out);
return out;
}
Which can then be used like this:
node n;
...
write(std::cout, n);
unique_ptr<node> n(...);
...
write(std::cout, *n);
And then you could take it a step further by changing the standalone function into a custom operator<< instead:
class node {
...
public:
...
void write(std::ostream &out) const;
};
std::ostream& operator<<(std::ostream &out, const node &n);
void node::write(std::ostream &out) const {
if (leftChild)
out << *leftChild << " ";
out << val;
if (rightChild)
out << " " << *rightChild;
}
std::ostream& operator<<(std::ostream &out, const node &n) {
n.write(out);
return out;
}
node n;
...
std::cout << n;
unique_ptr<node> n(...);
...
std::cout << *n;
First thing: void write(std::ostream &out) const; is NOT reference. It is declaration of a function.
Second: judging from const at the end of declaration it is method inside the class. Then you have to use scope operator (::) while defining method outside class body.
As for "blank results" nothing can be said without more code.

C++: Overloading << operator with function pointers

I have a class "stampstream" that is essentially intended to work like 'cout'. The two functions that follow are outside the class. This is the part that works.
class stampstream: public std::ostream
{
//code
stampstream& operator<<(stampstream& (*x)(void))
{
//code
}
//code
};
stampstream& endr()
{
//nocode
}
stampstream& (*endrow)(void)=endr;
In main:
stampstream s;
s << "teststring1" << endrow;
Note that "endrow" is essentially 'endl'. This part works perfectly fine, compiles and executes with the right output.
Now, I'm trying to overload << with another possible row(int) function. This is the part that doesn't work. Again, it's part of the same class as above and the following 2 functions are outside the class.
class stampstream: public std::ostream
{
//code
stampstream& operator<<(stampstream& (*r)(int y))
{
//code
}
//code
};
stampstream& ro(int y)
{
//nocode
}
stampstream& (*row)(int)=ro;
In main:
s << "teststring2" << row(5);
This is the error I get:
error: invalid user-defined conversion from ‘stampstream’ to ‘stampstream& (*)(int)’ [-fpermissive]
What am I doing wrong with row ?
The problem is that in
s << "teststring2" << row(5);
function call has higher precedence than <<, so this calls the function row points at and then tries to pass its return value (a stampstream &) to operator<<.
What you want is
s << "teststring2" << row;
This doesn't call the function and instead passes the pointer to operator<<. Inside that function, when you want to call x, you'll need to provide the argument.
It sounds like what you are trying to do is to have a function row that creates a functor object that you can then pass to operator<<. You can do that in C++11 with a lambda:
class stampstream: public std::ostream
{
//code
stampstream& operator<<(std::function<stampstream&(void)> r)
{
//code
}
//code
};
std::function<stampstream&(void)> row(int x)
{
return [x]()->stampstream & {
//code
}
}
Which you can call as:
s << "teststring2" << row(5);
The call to row happens first, which constructs a lambda and returns it (but doesn't yet run the code in it). The functor is passed to operator<< and when that function calls r, it will call the code in the lambda (which can refer to the x param, which was bound by value, so copied into the lambda.)
Since Chris has already answered your question, I wanted to advise you of alternatives to your current method:
Your stampstream class should use a specialized std::streambuf that writes out the stamp inside overflow(). There's no need to extend an std::ostream and reimplement the input operators. For an example of how to do this, see this thread.
You seem to be using endrow and row like manipulators. Operator overloads already exist for manipulators that do not take arguments at the call site. You can have endrow take and return an object of type std::ostream&. For row you can have it return a class that overloads the inserter to allow the syntax you want:
struct row_impl
{
row_impl(int row) : row(row) { }
// Write out the row and return the stream
friend std::ostream& operator<<(std::ostream& os, row_impl const& rimpl);
private:
int row;
};
std::ostream& operator<<(std::ostream& os, row_impl const& rimpl)
{
// This is where the code for your original row() function goes
}
// write out to and return the stampstream instance
std::ostream& endrow(std::ostream& os);
row_impl row(int row)
{
return row_impl(row);
}
Now s << endrow and s << row(5) will work without having to add anything to your stampstream class.

Overload operator in subclass

tour and guided tour. Guided tour extends the tour class. I'm overloading << and >> operators in the tour class.
My tour class looks like
#include <iostream>
#include <vector>
#include "Customer.h"
using namespace std;
class Tour {
protected:
string id;
string description;
double fee;
vector<string> customerList;
public:
Tour();
Tour(string idVal, string descriptionVal, double feeVal);
string getId();
string getDescription();
double getFee();
double getTotalForTour();
virtual void addCustomer(string cust);
vector<string> getCustomers();
virtual void display();
friend ostream& operator<< (ostream &out, Tour &cust);
friend istream& operator>> (istream &in, Tour &cust);
};
then my guided tour looks like this,
#include <iostream>
#include "Tour.h"
#include "SimpleDate.h"
using namespace std;
class GuidedTour : public Tour {
private:
SimpleDate* date;
string guideName;
int maxNumTourists;
public:
GuidedTour();
GuidedTour(string idVal, string descriptionVal, double feeVal, SimpleDate* dateVal, string guideNameVal, int maxNumTouristsVal);
virtual void addCustomer(string cust);
SimpleDate* getDate();
void display();
friend ostream& operator<< (ostream &out, GuidedTour &cust);
friend istream& operator>> (istream &in, GuidedTour &cust);
};
I want to overload these operators differently on the subclass to do something else.
I have a Vector that contains tours and guided tours.
When i loop through the vector and do following,
for (unsigned int i = 0; i < tourListVector.size(); i++) {
cout << *tourListVector[i];
}
It always does what's specified in tour regardless even if the object is a guided tour.
Can you please help?
You're almost doing the right thing, but not quite. Let's take the output case first -- the input case works just the same.
First, you should declare a
virtual void write(std::ostream&) const;
member function in your base class. The implementation might be something like:
void Tour::write(std::ostream& os) const
{
os << "ID: " << id << std::endl;
os << "Description: " << description << std::endl;
// etc
}
which I assume is the sort of code you have currently in your operator<<(ostream&, Tour&). Then you need to overload this in your derived class -- perhaps with something like
void GuidedTour::write(std::ostream& os) const
{
Tour::write(os); // Write out base Tour info first
os << "Guide Name: " << guideName << std::endl;
// etc
}
After that, you can declare a free (i.e. non-member) operator<< overload for Tours, which calls your write() member function, like
std::ostream& operator<<(std::ostream& os, const Tour& tour)
{
tour.write(os);
return os;
}
for example.
Explanation: Forget the fact that your current operator<< is a friend; it has no bearing in this case. Instead, imagine you have two overloaded non-member functions called
void do_something(Tour& t); // (a)
void do_something(GuidedTour& gt); // (b)
Since your tourListVector contains (I assume) Tour* pointers, if you were to loop through the vector and call do_something() on each element, the compiler would only be able to match function (a) above. That's because it has no way of knowing that some of the Tour* pointers might, for a given run of your programme, actually point to GuidedTour instances. In order to do run-time dispatching like this, you need to use virtual functions.
Aside: (I know this is example code, but if you're new to C++ then it's worth pointing out just in case you weren't aware :-) )
Because you're using Tour* pointers, you should define a virtual destructor for your base class. If you don't, the compiler won't know that it might need to destruct all the members of the GuidedTour class when you call delete on a Tour*. In fact, it's generally good practice to make your destructor virtual if your class includes any other virtual functions, just to save potential problems later.
Also, please don't put using namespace std; in a header file :-)
If i understood right, you have pointers in your vector. So you should use key word virtual. And read about virtual methods in C++.

Error: No operator << matches these operands?

I was practicing some c++ (trying to leave Java), and I stumbled on this annoying error saying:Error: No operater << matches these operands. I've searched this website for a clear answer and no luck, I did find that I'm not the only one.
This error is in my .cpp file, there are other errors, but I'm not paying any mind to them right now.
void NamedStorm::displayOutput(NamedStorm storm[]){
for(int i = 0; i < sizeof(storm); i++){
cout << storm[i] << "\n";
}
}
Something is up with the "<<" im not sure whats going on.
Since you are trying cout a class object you need to overload <<
std::ostream& operator<<(ostream& out, const NamedStorm& namedStorm)
You must overload the << operator in order to redirect your object into a stream.
You can overload as a member function, but in this case you must use the syntax object << stream in order to use that overloaded function.
If you wish to use this syntax stream << object then you must overload the << operator as a 'free' function, that is, not a member of your NamedStorm class.
Here is a working example:
#include <string>
#include <iostream>
class NamedStorm
{
public:
NamedStorm(std::string name)
{
this->name = name;
}
std::ostream& operator<< (std::ostream& out) const
{
// note the stream << object syntax here
return out << name;
}
private:
std::string name;
};
std::ostream& operator<< (std::ostream& out, const NamedStorm& ns)
{
// note the (backwards feeling) object << stream syntax here
return ns << out;
}
int main(void)
{
NamedStorm ns("storm Alpha");
// redirect the object to the stream using expected/natural syntax
std::cout << ns << std::endl;
// you can also redirect using the << method of NamedStorm directly
ns << std::cout << std::endl;
return 0;
}
The function which is called from the free redirection overload must be a public method of NamedStorm (in this case we are calling the operator<< method of the NamedStorm class), OR the redirection overload must be a friend of the NamedStorm class in order to access private fields.

Objects and Operator Overloading C++

class object_1
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_1 &obj_1);
friend object_2;
private:
char *pCh_mem1;
char *pCh_mem2;
int *pInt_mem1;
int *pInt_mem2;
};
class object_2
{
public:
...
friend ofstream& operator<<(ofstream &out, const object_2 &obj_2);
friend object_1;
};
Object1's implementation file is typical. Ctor, Dtor and some methods. I havent posted the method declarations in the header because their irrelevant to my problem.
It is very important that I discuss the objects lifetime.It is something that I really need to understand. Whats happening is that the operator overload function is then invoked when I call object_2 in main. So then the operator overload function is called:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
here we are:
void object_1::display(std::ostream &out)
{
out << left << setw(28) << "Person" << setw(20) << "Place" ;
out << right << setw(5) << "Thing" << setw(5) << "Idea" << endl;
out << left << setw(28) << "----" << setw(20) << "--------" ;
out << right << setw(5) << "----- " << setw(5) << "------" << endl;
}
At the top of the implementation file is the IOMANIP library. So setw(X) and everything are defined. Im getting 0's all prinited to the console. Did my object go out of scope? I think so because when i do all these before I need to, it works fine. That is, when I call this function n e where else than in the body of the operator overload it works. I think because the object is redeclared:
ostream& operator<<(ostream& out, const object_2& obj_2);
then after I print the formatting method I need to print the information that was passed in from main to the first object's ctor; object_1. When that happens we are in the overload function which is similar and its the same implementation file. Im calling both methods from the overload in the second objects overload function:
ostream& operator<<(ostream& out, const object_1& obj_1)
{
out << obj_1.pCh_mem1 << obj_1.pCh_mem2;
return out;
}
// main
object_2 obj_2(4);
static void method1()
{
//do stuff
}
static void method2()
{
//do stuff
}
static void method3()
{
//do stuff
}
int main(void)
{
method1();
method2();
method3();
cout << obj_2;
return 0; // and such
}
Once objc_2 is called like u see above, the operator overload for object2's class will then be called. I cant use any of my private members because its an illegal operatation. I guess my questions is. How can i print my private members from object1 in my object2's operator overloading function? static_cast's? I have a random snippet from main, Its complicated and I cant alter it.
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
What i've been trying to do, like you see above is call the other objects methods, and get the info from their. But that info is all NULL!! Im hopping from one I.F. to the next and its all NULL!!
AFAICT, object_1 and object_2 are unrelated classes (except that they are friends). So an object_2 does not have any state relevant to an object_1.
Therefore, when you try to print an object_2 as if it were an object_1, this cannot possibly work. It is surprising that this call works at all:
ostream& operator<<(ostream& out, const object_2& obj_2)
{
object1::display(out) //Calls method display in object1's I.F.
return out;
}
since there is no object_1 around here for which a method can be called (but then, you probably didn't mean this to be real code, since it's missing a semicolon also).
It's not completely clear what you want to achieve. Maybe you want object_2 to inherit from object_1, so that any object_2 will also have the members pCh_mem1 etc? Maybe you want a member of object_2 to be an object of type object_1?
ostream& operator<<(ostream& out, const object_2& obj_2)
{
out << object_1[thatIndexThatIstoreditAt]
return out;
}
I need to write a few reports on this stuff. =)