请看我第一次回答这个问题的尝试。为了使事情简单化,我之前没有把整个事情讲清楚。事实证明我的例子是有效的!对不起。
整个故事是这是一个库,在一个文件中包含一个类,在另一个文件中包含main,所有这些都链接到我的库中。库为过程框架提供了基础,这就是为什么main在库中而不是在过程中。
下面是我所拥有的一个简化版本。
pf.hpp
using namespace std;
namespace MyNamespace
{
class ProcessManager
{
public:
friend int main(int argc, char** argv);
private:
void test();
};
};
pf.cpp
#include "pf.h"
namespace MyNamespace
{
ProcessManager::test()
{
cout << "My friend has accessed my member" << endl;
}
};
pfmain.cpp
#include "pf.hpp"
int main(int argc, char** argv)
{
ProcessManager pm;
pm.test();
}
注意,这在编译库
时会失败我试过的是:
- 移动朋友
- 使友元引用到main使用全局作用域(例如::main)
- 使友元和主元声明使用全局作用域
我错过了什么?
谢谢!
在MyNamespace
之外声明main,并在友元语句中指定全局命名空间::
//in header file of ProcessManager
//your pf.h
int main(int argc, char** argv);
namespace MyNamespace
{
class ProcessManager
{
public:
friend int ::main(int argc, char** argv);
private:
void test();
};
};
@parapura提供了一个解决方案,但没有解释为什么首先必须在全局作用域中声明main
。
§7.3.1.2 [namespace.memdef] p3
因此,考虑到这一点,你的代码看起来像这样:[…如果非局部类中的
friend
声明首先声明了一个类或函数,则友类或函数是最内层封闭命名空间的成员。[…]
namespace MyNamespace
{ // MyNamespace is the innermost enclosing namespace
// 'main' from the friend declaration is treated
// as if it was a member of 'MyNamespace'
int main(int argc, char** argv);
class ProcessManager
{
public:
friend int main(int argc, char** argv);
private:
void test();
};
};
现在应该清楚了,为什么全局main
函数不是您的朋友。
一个常见的答案可能是提供一个"application"单例类,例如Qt中的QApplication,并将您的main
减少到类似
int main (int argc, char** argv) {
YourApplication app (argc, argv);
return app.execute();
}
然后你减少了你对class YourApplication
和其他类的友好性关注,你知道怎么做。
我不认为你真的想做你正在做的事情。这看起来真的像是一个黑客和设计问题。如果你真的想在某些特殊情况下公开你的类的内部,你可以创建一个访问器类,它也定义在你的库中。
类似这样的操作可能会起作用(可能需要适当的前向声明等——这只是一个起点):
class ProcessManagerAccessor
{
public:
ProcessManagerAccessor(ProcessManager & pm) : pm_(pm) { }
// add public methods to expose internals
void test() { pm_.test(); }
private:
ProcessManager & pm_;
};
class ProcessManager
{
public:
friend class ProcessManagerAccessor;
// ...
};
// ...
ProcessManager pm;
ProcessManagerAccessor pma(pm);
pma.test();