如何在图书馆内为我的班级的朋友制作主?

时间:2011-12-23 18:18:52

标签: c++ main friend

请参阅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();
}

请注意,这在编译库

时失败

我试过的是:

  • 将朋友移到各处
  • 让朋友引用主要使用全局范围(例如:: main)
  • 使朋友和主要声明使用全局范围

我错过了什么?

谢谢!

4 个答案:

答案 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();