4

I'm trying to overload the << operator for a class to emulate toString() in Java. I have a NumExpr class, and has private variable number that I want to output. so here they are:

NumExpr::NumExpr( string n ) {
    number = atoi( n.c_str() );
}
string NumExpr::name() {
    return "num";
}
ostream & operator<<(ostream &s, const NumExpr &num) {
    s << num.number;
    return s;
}

I made it a friend function so it can access the private variable

class NumExpr : public Expr {
    public:
        NumExpr( string v );
        string name();
    private:
        int number;
        friend ostream& operator<<(ostream &s, const NumExpr &num);
};

However I'm getting this error

./ast/Expr.cpp: In function ?std::ostream& operator<<(std::ostream&, const NumExpr&)?: ./ast/Expr.cpp:50: error: no match for ?operator<NumExpr::number? ./ast/Expr.cpp:49: note: candidates are: std::ostream& operator<<(std::ostream&, const NumExpr&)

I have searched for this error, people seem to be having the same problems but mine seems to look like the solutions people are giving out. Is there something fundamentally wrong that I'm doing or is there some syntax shenanigans that I'm not aware of?

Thanks for the help!

Jason Hu
  • 1,237
  • 2
  • 15
  • 29
  • 1
    [This works fine](http://ideone.com/evv9X) as long as you are creating the object `NumExpr` by using proper constructor. – Alok Save May 28 '12 at 05:53
  • 2
    It compiles: http://ideone.com/aZTvQ . Can you show us the calling code? – Naveen May 28 '12 at 05:53
  • 1
    interesting! I haven't added the calling code for the function yet. Its just freshly made and having problems without me having to call it. By the way I am using the g++ command on linux if it helps any. @Naveen Hmm, that looks like how I would instantiate the class, not sure why its not working out on my side. – Jason Hu May 28 '12 at 05:57

2 Answers2

6

Okay here it is, little bit of playing around I can reproduce your problem:

The problem is that You forgot to include iostream header file.
Add:

#include<iostream>

and it should just work fine :)

EDIT:
As @James Kanze correctly suggests in comments, it is sufficient to include

#include<istream>

because you don't need everything from the iostream really.
The downside of including iostream inside of istream is little increase in compilation time.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 3
    Wow, that's.....wow. I was wondering why it was having issues with the int, but I guess I was overthinking again. – chris May 28 '12 at 06:02
  • Oh noes the deadly header inclusion! Thanks :) – Jason Hu May 28 '12 at 06:03
  • On a side note if anyone knows (Don't wanna start another question) If I call the overloaded operator in the derived class that has a pointer which was originally a pointer to the base class, which overloaded function will it call? ie something like: `NumExpr* numexpr = new NumExpr; FExpr* expr = numexpr; cout << expr;` – Jason Hu May 28 '12 at 06:09
  • @JasonHu: In that case,You would end up getting a compilation error if you did `cout << *expr;`, You have no overloaded `<<`for `Expr` class, So compiler would try to search appropriate overload with `cout` and will fail since `Expr` is your custom data type. If you did a `cout << expr;` It would print the address of the pointer, which is not what you intend I believe. – Alok Save May 28 '12 at 06:13
  • is there an alternate way to approach this? I'm coming from the java background where it was okay to overload the toString() method which was interited – Jason Hu May 28 '12 at 06:16
  • @JasonHu: Alternate way to what? I don't understand the problem statement. If you need to use `<<` on a class you need to provide an overload for that class. In this case for the Base class `Expr`. – Alok Save May 28 '12 at 06:20
  • oh sorry I am trying to print out the contents of the class ultimately... However at any point in my program I'm always treating my objects as the base class because I have no knowledge if that `Expr` is an instance of any of its derivative classes. So I would want my `<<` to print out the contents inside of the overloaded operator for the derived classes. However from your comments above it seems that it would print out the contents of the base class `Expr`, which is unfortunate. – Jason Hu May 28 '12 at 06:24
  • @JasonHu: Okay, We make a fast call to Polymorphism for your rescue :), You add a pure virtual function `print()` in Base class, and call this function through overloaded `<<` operator of the Base class,`print()` is overidden in each of the derived classes and it calls `<<` on `this`, We make sure we pass the object by reference to Base class `<<` which enables the dynamic dispatch.Here's a [code sample](http://ideone.com/WIz1m) which shows how to. – Alok Save May 28 '12 at 06:50
  • Including just `` should be sufficient. You don't need everything in ``. – James Kanze May 28 '12 at 07:32
  • @JamesKanze: I agree.Is there any overhead other than importing unwanted symbols? In C++ One pays only for what is used so only overhead involved is probably compilation time & namespace pollution? – Alok Save May 28 '12 at 07:36
  • @Als The major cost in using `iostream` when you don't need it is in compilation time. You're including significantly more lines of code which have to be read and parsed. Historically, it made a significant difference. Today, I don't know. It probably depends on your compiler and your project. – James Kanze May 28 '12 at 08:07
0

On this page:

http://www.cplusplus.com/forum/beginner/13164/

It says to have the friend function like this:

friend std::ostream& operator<< (std::ostream&, const NumExpr&); <- 

so no variable decleration. just

const NumExpr

any help?

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175