Hello,
I am trying to code the example given in "Ruminations on C++" Koenig, Moo, §8.3 but I don't get it to run like shown in the book.
Here is my minimized example:
compile:
g++ main.cpp expr.cpp
main.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
#include <iostream>
#include "expr.hpp"
using std::cout;
using std::endl;
int main(int argc, char** argv)
{
Expr t(5);
cout << t << endl;
return 0;
}
|
expr.hpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#ifndef EXPR_H
#define EXPR_H
#include <iostream>
#include "expr_node.hpp"
class Expr
{
friend std::ostream& operator<<(std::ostream&, const Expr&);
public:
Expr(int);
~Expr();
private:
Expr_node* p;
};
#endif
|
expr.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#include "expr.hpp"
#include "int_node.hpp"
Expr::Expr(int k)
{
p = new Int_node(k);
}
//------------------------------------------------------------------------------
Expr::~Expr()
{
if (--(p->use) == 0) delete p;
}
//------------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& o, const Expr& e)
{
e.p->print(o);
return o;
}
|
expr_node.hpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
#ifndef EXPR_NODE_H
#define EXPR_NODE_H
#include <iostream>
#include "expr.hpp" //has no effect because of GUARD
class Expr_node
{
class Expr;
friend std::ostream& operator<<(std::ostream&, const Expr&); //-> op<< needs access
friend class Expr; //-> Expr class needs access to "use" and ~Expr_node()
protected:
Expr_node(): use(1) { }
virtual void print(std::ostream&) const = 0;
virtual ~Expr_node() { }
private:
int use;
};
#endif
|
int_node.hpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
#ifndef INT_NODE_H
#define INT_NODE_H
#include <iostream>
class Int_node: public Expr_node
{
friend class Expr; //-> Expr class constructs Int_nodes via Int_node(int)
private:
int n;
void print(std::ostream& o) const {o << n;}
Int_node(int k): n(k) { }
};
#endif
|
The program compiles and runs if I
- remove the forward declarion
- remove the friendship to operator<<
- declare print() as public
but there is no reason why print() should be public and it is protected in the book! If I set print() as protected, I need the friendship with operator<< because this function uses print() in expr.cpp line 17:
e.p->print(o);
As the friendship declaration has the Expr type in its arguments I need to forward declare class Expr. (otherwise "Expr doesn't name a type" error).
Doing so causes the compiler error:
expr.cpp:7:22: error: ‘Int_node::Int_node(int)’ is private within this context |
BUT: class Expr is friend of Int_node.
I do not understand how the forward declaration in one class (expr_node) can cause a problem in another class (expr).
Can someone see what is going wrong here?
Thanks in advance.