当一个友元函数包含在命名空间中时,它的定义需要以命名空间为前缀来编译它,这里是示例代码:
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
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
编译上面的代码会给出错误:
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'
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用
void TestNamespace::testFunc(TestClass &myObj)
{
int j = myObj.i;
}
Run Code Online (Sandbox Code Playgroud)
它编译,为什么函数需要以命名空间TestNamespace :: testFunc为前缀而不是类,类TestClass和函数testFunc都包含在头文件中的命名空间中.
所述TestClass被在所使用的testFunc方法.由于您已包含命名空间" using namespace TestNamespace;",因此它可以正常工作.
对于testFunc定义实现的方法,需要告诉编译器testfunc属于命名空间TestNamespace:
你也可以这样做:
在.cpp
namespace TestNamespace
{
void testFunc(TestClass &myObj)
{
int j = myObj.i;
}
}
Run Code Online (Sandbox Code Playgroud)
要么
void TestNamespace::testFunc(TestClass &myObj)
{
int j = myObj.i;
}
Run Code Online (Sandbox Code Playgroud)
在为命名空间实现cpp时,我没有执行"using namespacename;" 事情.相反,我声明命名空间就像在.h文件中一样,并在其中嵌入所有命名空间代码.像这样:
namespace Namespacename {
classname::methodname () { ... };
...etc.
}
Run Code Online (Sandbox Code Playgroud)
它为您和编译器避免了很多混乱.
所以你的代码应该是这样的:
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
就政策问题而言,我总体上试图避免"使用"."std"可能是可以接受的,但对于其他一切,我希望读者知道它来自哪里.只要您在命名事物时采取命名空间应该成为对象名称的一部分的态度,这就不是那么困难了.
例如,在上面的代码中,我将命名空间命名为"Test",并从其所有方法和类中取出"Test"一词.这样,您的客户只需声明一个,而不是做一个using TestNamespace;并TestClass声明一个Test::Class.这样,Test实际上是一个编译器强加给你的对象的结构,而不仅仅是一块非结构化的元数据,你必须把它们放在你名字的前面以暗示一种关系.