friend function within a namespace
When a friend function is included in the namespace, its definition needs to be prefixed with namespac开发者_开发知识库e to compile it, here is the sample code:
test.h:
#ifndef TEST_H
#define TEST_H
namespace TestNamespace
{
class TestClass
{
public:
void setValue(int &aI);
int value();
private:
int i;
friend void testFunc(TestClass &myObj);
};
void testFunc(TestClass &myObj);
}
#endif
test.cpp:
#include "test.h"
using namespace TestNamespace;
void TestClass::setValue(int &aI)
{
i=aI;
}
int TestClass::value()
{
return i;
}
void testFunc(TestClass &myObj)
{
int j = myObj.i;
}
Compiling above code give the error :
1>c:\qtprojects\namesp\test.cpp(17) : error C2248: 'TestNamespace::TestClass::i' : cannot access private member declared in class 'TestNamespace::TestClass'
1> c:\qtprojects\namesp\test.h(11) : see declaration of 'TestNamespace::TestClass::i'
1> c:\qtprojects\namesp\test.h(6) : see declaration of 'TestNamespace::TestClass'
However if i use
void TestNamespace::testFunc(TestClass &myObj)
{
int j = myObj.i;
}
It compiles, Why the function needs to be prefixed with namespace TestNamespace::testFunc but not the class, Both the class TestClass and function testFunc are included in the namespace in header.
The TestClass
is being used in the testFunc
method. Since you have included the namespace "using namespace TestNamespace;
" it works fine.
For testFunc
method you are defining the implementation, you need to tell compiler that testfunc belongs to namespace TestNamespace:
you can do it either:
in .cpp
namespace TestNamespace
{
void testFunc(TestClass &myObj)
{
int j = myObj.i;
}
}
OR
void TestNamespace::testFunc(TestClass &myObj)
{
int j = myObj.i;
}
When implementing cpp's for namespaces I don't do the "using namespacename;" thing. Instead, I declare the namespace just like in the .h file and embed all the namespace code in that. Like so:
namespace Namespacename {
classname::methodname () { ... };
...etc.
}
It avoids a lot of confusion, both for you and the compiler.
So your code should look like:
#include "test.h"
namespace TestNamespace {
void TestClass::setValue(int &aI)
{
i=aI;
}
int TestClass::value()
{
return i;
}
void testFunc(TestClass &myObj)
{
int j = myObj.i;
}
}
Just as a matter of policy, I try to avoid "using" in general. It is probably acceptable for "std", but for everything else I want the reader to know where stuff came from. This isn't that much of a hardship as long as you take the attitude that the namespace should be part of the object's name when you are naming things.
For example, in your above code I'd name the namespace "Test" and take the word "Test" out of all its methods and classes. That way instead of doing a using TestNamespace;
and declaring a TestClass
, your client will simply declare a Test::Class
. This way Test is actually a piece of compiler-imposed structure to your objects, rather than just a piece of unstructured metadata that you have to chuck onto the front of your names to imply a relationship.
There is actually no way the compiler can tell if your function definition in the cpp file
void testFunc(TestClass &myObj)
{
int j = myObj.i;
}
belongs to the already declared prototype
void TestNamespace::testFunc(TestClass &myObj);
or is a new function without a forward declaration. So the only way to resolve the ambiguity is to make you resolve the namespace. Hence the error message.
When emitting an implementation, the default namespace is the global namespace whereas:
using namespace TestNamespace;
tells the compiler 'look in here if I don't prefix' somewthing I'm referencing.
To get the behaviour you were anticipating, you could wrap the contents of the .cpp file (excluding the includes) in a whole-file namespace {} declaration
精彩评论