0

I'm working on extraction and insertion overloads. And I can't access the private variables while using friend.

This is my code based a standard tutorials and what my teacher gave me to work with

Main.cpp

#include <iostream>
#include "Obj.h"

using namespace std;
using namespace N;

Obj a;

int main() {
  cout << a;
}

Obj.cpp

#include "Obj.h"
#include <iostream>

using namespace std;
using namespace N;

ostream &operator<<(ostream &output, const Obj &a) {
    output << a.h;
    return output;
}

Obj.h

#ifndef OBJ_H
#define OBJ_H

#include <iostream>

using namespace std;

namespace N {
    class Obj {
        private:
        string h; 

        public:

        //constructors
        Obj() {
            h = "default";
        }

        //overloads
        friend ostream &operator<<(ostream &output, const Obj &a);
    };
}

#endif

I started from a header file setup and broke it down to this while getting the same error code. In particular I keep getting this result.

Obj.cpp:9:15: error: 'h' is a private member of 'N::Obj'
  output << a.h;
              ^
./Obj.h:12:14: note: declared private here
      string h; 
Chris
  • 26,361
  • 5
  • 21
  • 42
ron252
  • 21
  • 8
  • 3
    Can't [reproduce](https://godbolt.org/z/G5jvEWhMq) – cigien Sep 19 '21 at 21:28
  • Welcome to Stack Overflow! Can you edit your question to show the exact contents of the `.h` and `.cpp` files you're using? The code you've shown above should work just fine, which leads me to think something else might be going on. – templatetypedef Sep 19 '21 at 21:29
  • My crystal ball (such as it is) suggests that you have a *very minor* difference between the declaration and definition of your overloaded (friend) `<<` operator. Possibly, one is missing a `const` or a `&`? – Adrian Mole Sep 19 '21 at 21:31
  • I can do you one better and show yo the project. https://replit.com/@QuietQuiet/Insertion-Operator#main.cpp I'll edit the question as well – ron252 Sep 19 '21 at 21:36

2 Answers2

2

The issue is with the fact that you declare your friend function in namespace N, but you define it in the global namespace. using namespace N; does not put any definition in the namespace, it only lets compiler guess that it should be from that namespace if it has other clues for that (e.g. you are defining a method of a class). Here, there's nothing to suggest that this operator should not be in the global namespace, so it is there.

The solution is use namespaces correctly:

#include "Obj.h"
#include <iostream>

using namespace std;
namespace N {

ostream & operator << (ostream &output, const Obj &a){
  output << a.h;
  return output;
}

}

And while we're at it, using namespace std; is not a good practice either.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
0

Put the body of << in the class declaration.

It can be as short as a.printTo(output); return output;.

Then write printTo.

The rules for introducing a name as a friend declaration are sometimes tricky. I'm guessing your real code, Obj is a template, or some minor chsnge messes up the match, etc. The above pattern sidesteps those issues.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524