Hi all,

This is my first post here.

Basically I want to use friend classes across namespace. eg:

#include <iostream>

namespace NamespaceA {

    class ClassA {
    public:
        friend class ClassB;
        void print( ) {
            std::cout<<std::endl<<data<<std::endl;
        }
    private:
        int data;
    };
};

namespace NamespaceB {
    class ClassB {
    public:
        ClassB() {
            NamespaceA::ClassA obj;
            obj.data = 10;
            obj.print();
        }
    };
};

int main(int argc, char *argv[])
{
    NamespaceB::ClassB obj;

    return 0;
}

When I compile this, I get following error,

main.cpp: In constructor `NamespaceB::ClassB::ClassB()':
main.cpp:12: error: `int NamespaceA::ClassA::data' is private
main.cpp:21: error: within this context

How to fix this error?

FYI, some body has written about this in
http://stupefydeveloper.blogspot.com/2008/04/c-friend-classes-in-namespaces.html

But I didn't understand the solution.

Dani AI

Generated

Nice catch. The error is just name lookup. Inside NamespaceA, the line friend class ClassB; is an unqualified name, so the compiler looks in NamespaceA (and enclosing scopes) first. It does not find NamespaceB::ClassB, so no friendship is granted and data stays private. To befriend something in another namespace you must name it with its full scope, and that type must be declared before the friend line. Your forward declaration + qualified friend is the right fix. See the rules on friend declarations and unqualified lookup for why this happens. Friend declaration - cppreference. Unqualified name lookup - cppreference.

If you only need one operation, consider befriending just a member function instead of the entire class. That keeps the surface area smaller:

// Forward decls so the names exist
namespace NamespaceA { class ClassA; }
namespace NamespaceB {
  class ClassB {
  public:
    void set(NamespaceA::ClassA&, int);
  };
}

// Grant friendship to that specific member
namespace NamespaceA {
  class ClassA {
    friend void NamespaceB::ClassB::set(ClassA&, int);
  private:
    int data = 0;
  };
}

// Definition after both classes are known
inline void NamespaceB::ClassB::set(NamespaceA::ClassA& a, int v) { a.data = v; }

Practical tips:

  • Place the forward declarations in a small header included by both A and B to avoid circular includes.
  • using namespace NamespaceB; will not rescue an unqualified friend class ClassB; here; use the qualified name.
  • Friendship is not inherited or transitive, so keep it as narrow as possible. Friend declaration - cppreference.

Found the solution my self,

#include <iostream>

namespace NamespaceB {
    class ClassB;
};

namespace NamespaceA {

    class ClassA {
    public:
        friend class NamespaceB::ClassB;
        void print() {
            std::cout<<std::endl<<data<<std::endl;
        }
    private:
        int data;
    };
};

namespace NamespaceB {
    class ClassB {
    public:
        ClassB() {
            NamespaceA::ClassA obj;
            obj.data = 10;
            obj.print();
        }
    };
};

int main(int argc, char *argv[])
{
    NamespaceB::ClassB obj;

    return 0;
}

shall fix it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.