请参阅my first attempt at answering this 。为了简化事情,我忽略了讲述整个故事。结果我的例子工作!遗憾。
整个故事是,这是一个库,在一个文件中包含一个类,另一个文件中包含一个主,所有这些都链接到我的库中。该库提供了流程框架的基础,这就是为什么主要是在库中而不是流程。
以下是我所拥有的精简版。
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();
}
请注意,这在编译库
时失败我试过的是:
我错过了什么?
谢谢!
答案 0 :(得分:10)
只需在MyNamespace
之外声明主要内容,并在友好声明中指定全局命名空间::
//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();
};
};
答案 1 :(得分:2)
@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
功能不是你的朋友。
答案 2 :(得分:0)
一个常见的答案可能是提供一个“应用程序”单例类,例如Qt QApplication,将main
缩小为
int main (int argc, char** argv) {
YourApplication app (argc, argv);
return app.execute();
}
然后你减少了对class YourApplication
与其他课程的友情关系,你知道该怎么做。
答案 3 :(得分:0)
我认为你真的不想做你正在做的事情。这看起来像是一个黑客和设计问题。如果你真的想在某些特殊环境中暴露你的类的内部,你可以创建一个也在你的库中定义的访问者类。
这样的事情可能有用(可能需要适当的前瞻声明等等 - 这只是一个起点):
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();