0

In a named namespace class, I declare a class (which is in the global namespace) as friend. However, the latter class cannot access the private member of the former class. Why is this? Is there any way around it?

Bob.h

namespace ABC {
    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

Bob.cc

#include "Bob.h"

ABC::Bob::Bob () {
    pub_number=10;
    priv_number=6;
}

Joe.h

class Joe {
    Joe ( );
};

Joe.cc

#include "Joe.h"
#include <iostream>
#include "Bob.h"

Joe::Joe ( ) {
    ABC::Bob b;
    std::cout << b.pub_number << std::endl;
    std::cout << b.priv_number << std::endl;
}

The above code produces the following error when compiled:

Joe.cc:8:16: error: ‘int ABC::Bob::priv_number’ is private within this context
INFO: 1>     8 | std::cout << b.priv_number << std::endl;

If I do the same code as above, but without any namespace for the "Bob" class, then the code compiles.

I have attempted to forward declare the Joe class in Bob.h as follows:

class Joe; // This does nothing to help

class ::Joe // This produces compiler message "error: ‘Joe’ in namespace ‘::’ does not name a type"
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
didjek
  • 393
  • 5
  • 16
  • Where in `Bob.h` did you put the forward declaration of `Joe`? If it's inside `namespace ABC` it does not declare the same class as in the global namespace. – StoryTeller - Unslander Monica Sep 15 '20 at 11:09
  • I tried putting it in different places. I tried outside the namespace, inside the namespace and inside the class. All gave the same results. – didjek Sep 15 '20 at 11:13

3 Answers3

1

You need add both an unscoped forward declaration in the global namespace, as well as use the scoping operator when declaring the friend:

class Joe;  // Forward declaration

namespace ABC {
    class Bob {
        friend class ::Joe;  // Use the Joe class from the global scope
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I saw some code where the friend declaration was in "private", is there any reason to put it there ? – didjek Sep 15 '20 at 11:20
  • @didjek `friend` declarations are independent of access specifiers like `public` or `private`. Their placements is up to personal preference. – Some programmer dude Sep 15 '20 at 11:24
0

Your friend declaration needs the :: prefix, too:

class Joe;

namespace ABC {
    class Bob {
        friend class ::Joe;
        //           ^^ here

        ...
     };
 }
lubgr
  • 37,368
  • 3
  • 66
  • 117
0

In this class definition

namespace ABC {
    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

the declaration of the friend class Joe introduces the name Joe in the scope of the namespace ABC because a prior declaration of the class Joe is not visible and there is used an unqualified name.

From the C++ Standard (10.3.1.2 Namespace member definitions)

  1. ... If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

You need to place a declaration of the class Joe in the global namespace before the declaration of the class Bob and within the class Bob you have to use a qualified name of the friend class at least like

class Joe;

namespace ABC {
    class Bob {
        friend class ::Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}

Or you could use a using declaration in the namespace ABC like

class Joe;

namespace ABC {
    using ::Joe;

    class Bob {
        friend class Joe;
        public:
            Bob ();
            int pub_number;
        private:
            int priv_number;
    };
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335