file.cpp

#include "file.h" namespace NS { void f(const A &obj) { std::cout << obj.data; } } 

file.h

 class A { private: int data; friend void NS::f(const A &obj); } 

The compiler swears at this. If you describe NS in file.cpp to class A, then everything works. Tell me, please, what I do not understand? Why it happens? How to make it work when NS is in a different file?

UPD: and in the same file does not work. "Using indefinite type A"

  • "If you describe NS in file.cpp to class A ..." What does "in file.cpp to class A" mean, if in "file.cpp" you have no "class A"? "class A" is in file.h. - AnT

3 answers 3

This is fixed like this:

file.cpp remains unchanged.

The following is written to file.h :

 class A; namespace NS { void f(const A &obj); } class A { private: int data; friend void NS::f(const A &obj); } 

Why didn't your option work?

First, the compiler did not know what NS : a namespace or class, or something else.

However, even if you add it over the namespace NS {} class, it will not work anyway, but this time the error will be different: error: 'void NS::f(const A&)' should have been declared inside 'NS' (c) GCC .

Be f in the same namespace as the class, friend void f(const A &); would work without a function declaration. (This line itself would be a function declaration, although it would be possible to reach its normal (re) declaration only through an argument-dependent lookup.)

Why is that? Apparently the developers of the standard decided that declaring functions in arbitrary namespaces from classes in other namespaces is a brute force.

    You can use the friendship with the function, if only this function is declared in advance. You can declare a function, but you need to declare a class in advance. No matter in what file you will do it, the main order.

     # include <iostream> class A; namespace NS{ void f(const A &obj); } class A { private: int data; friend void NS::f(const A &obj); }; namespace NS { void f(const A &obj) { std::cout << obj.data; } } 

      In C ++, qualified names, such as NS::f , are used only to refer to previously declared ones, i.e. entities already known to the compiler. Want to use a qualified name - make sure that the entity referenced by this name is declared in advance. Simply put, such entities should be declared higher in the file.