我如何在图书馆里结交同班同学的朋友?



请看我第一次回答这个问题的尝试。为了使事情简单化,我之前没有把整个事情讲清楚。事实证明我的例子是有效的!对不起。

整个故事是这是一个库,在一个文件中包含一个类,在另一个文件中包含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();

相关内容

  • 没有找到相关文章

最新更新