1

I get this when i try to compile:

../Monster.h:26:9: error: ‘int ProjectIV::Monster::con’ is private

`int con;`
     ^

../Monster.cpp:17:39: error: within this context

cout << "Constitution: " << monster.con << endl; ^

make: * [Monster.o] Error 1

From what I understand making operator<< a friend should allow it to access int con. What am I not seeing.

Monster.h:

#ifndef MONSTER_H_
#define MONSTER_H_

#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
#include <string>
using std::string;

namespace ProjectIV
{
  class Monster
  {
  friend ostream &operator<< (ostream &out, const Monster &monster);
  public:
    Monster(int con);
  private:
    int con;
  };
} /* namespace ProjectIV */

#endif /* MONSTER_H_ */

Monster.cpp:

#include "Monster.h"

ostream &operator<< (ostream &out, const ProjectIV::Monster &monster)
{
  cout << "Constitution: " << monster.con << endl;

  return out;
}

ProjectIV::Monster::Monster(int con): con(con)
{}

main.cpp:

#include "Monster.h"
using namespace ProjectIV;

int main()
{
  Monster Gojira(140);
  cout << Gojira << endl;
  return 0;
}
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
deadpickle
  • 115
  • 2
  • 15
  • 2
    You should not use "using" at global scope in header files: http://stackoverflow.com/a/2717709/4323 This probably won't fix your problem, but it's good advice for C++. :) – John Zwinck Feb 01 '14 at 01:52

2 Answers2

2

This:

ostream& operator<<(ostream& out, const ProjectIV::Monster& monster)

should be:

ostream& ProjectIV::operator<<(ostream& out, const ProjectIV::Monster& monster)

Here your not working example, and here is the working one.


Also, as per AndreyT's comment, you should add a function declaration before the friend declaration:

namespace ProjectIV {
    class Monster {
    friend ostream& operator<<(ostream& out, const Monster& monster);
    public:
        Monster(int con);
    private:
        int con;
    };
    ostream& operator<<(ostream& out, const Monster& monster);
    // ^^^ this
}
Community
  • 1
  • 1
Shoe
  • 74,840
  • 36
  • 166
  • 272
  • This is not enough. Friend declaration *refers* to `ProjectIV::operator<<`, that is true. But it does not introduce a declaration for `ProjectIV::operator<<` into `ProjectIV` namespace. Without such declaration, it is illegal to define `ProjectIV::operator<<` in global namespace. G++ rejects the code. An explicit declaration for `operator<<` must be added to `ProjectIV` namespace. (clang++ apparently accepts the code.) – AnT stands with Russia Feb 01 '14 at 02:26
  • @AndreyT, true. Thanks. That's weird that Clang++ accepts it instead. – Shoe Feb 01 '14 at 02:34
0

There are two problems with your code.

Firstly, the friend declaration inside Monster class refers to ProjectIV::operator << function. It is ProjectIV::operator << that will become the friend of Monster. What you defined in your Monster.cpp file is actually a ::operator <<. This is a completely different function that is not a friend of Monster. This is why you get the error.

So, you need to decide what function you want to make a friend - the one in global namespace or the one in ProjectIV namespace - and act accordingly.

If you want to make your operator << a member of ProjectIV namespace, you run into the second problem. Friend declarations refer to member of enclosing namespace, but they don't introduce the corresponding declarations into the enclosing namespace. It is still your responsibility to add a declaration for operator << in ProjectIV

namespace ProjectIV
{

  class Monster
  {
  friend ostream &operator<< (ostream &out, const Monster &monster);
  public:
    Monster(int con);
  private:
    int con;
  };

  ostream &operator<< (ostream &out, const Monster &monster);

} /* namespace ProjectIV */

and then later define it as a member of ProjectIV

ostream &ProjectIV::operator<< (ostream &out, const ProjectIV::Monster &monster)
{
  cout << "Constitution: " << monster.con << endl;

  return out;
}
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765