How do I make main a friend of my class from within a library?

﹥>﹥吖頭↗ 提交于 2019-12-19 05:58:15

问题


Please see my first attempt at answering this . I neglected to tell the whole story before in an attempt to simplify things. Turns out my example works! Sorry.

The whole story is that this is a library the contains a class in one file and the main in another file, all linked into my library. The library is providing the basis for a Process Framework, which is why the main is in the library and not the process.

Below is a stripped down version of what I have.

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

Note that this fails on the compilation of the library

What I have tried is:

  • Moving the friend all over the place
  • Making the friend reference to main use global scope (e.g. ::main)
  • Making friend and main declarations use global scope

What am I missing?

Thanks!


回答1:


Just declare the main outside the MyNamespace and specify global namespace :: in friend statement

//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();
  };
};



回答2:


@parapura provided a solution, but doesn't explain why you first have to declare main in the global scope.

§7.3.1.2 [namespace.memdef] p3

[...] If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. [...]

So with that in mind, your code would look somewhat like this:

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

Now it should be clear why the global main function wasn't your friend.




回答3:


A common answer might be to provide an "application" singleton class, like e.g. QApplication in Qt, an reduce your main to something like

int main (int argc, char** argv) {
    YourApplication app (argc, argv);
    return app.execute();
}

Then you reduce your friendness concern to class YourApplication vs your other classes, and you know how to do that.




回答4:


I don't think you actually want to do what you are doing. This really seems like a hack and a design problem. If you really want to expose the internals of your class in some specialized circumstance, you could make an accessor class which is also defined inside your library.

Something like this might work (may need appropriate forward declarations, etc. -- this is just a starting point):

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


来源:https://stackoverflow.com/questions/8619356/how-do-i-make-main-a-friend-of-my-class-from-within-a-library

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!