29

I am porting code from Java to c++ and I'd like to replicate some anonymous functionalities.

In file A.h I have :

class A
{
private:
  int a;

  class AnonClass;
  friend class AnonClass;
};

In file A.cpp I have :

namespace
{
  class AnonClass
  {
  public:
    AnonClass(A* parent)
    {
      parent->a = 0; // This doesn't work, a is not accessible
    }
  }
}

Is it possible to friend a class in an anonymous namespace in C++?

In Java you can declare anonymous classes so it would be very similar. Also it would not expose AnonClass to clients of A.h

Eric
  • 19,525
  • 19
  • 84
  • 147
  • Have you tried to do this? (With out "class AnonClass;" line). AFAIK, You can declare it like this, but when you use AnonClass you will have to specify the namespace. Is it what you want? – klm123 Nov 09 '13 at 06:03
  • I can't compile yet to be frank, I have tons of unmodified functions and classes to create to get any hope of compiling. I use VS2012 error auto detection for this. I tested the above code but it doesn't work – Eric Nov 09 '13 at 06:14
  • Without "class AnonClass;", it doesn't compile either because AnonClass is undefined – Eric Nov 09 '13 at 06:17
  • 1
    That's probably because you likely didn't forward-declare the AnonClass (you have to declare a class before (above where) you use it). Your "class AnonClass" line is defining a class called A::AnonClass (internal class of A), which is distinct from the other. You at least need to put the "class AnonClass" line above the class A definition (which doesn't necessarily fix your namespace problem). – leewz Nov 09 '13 at 07:18
  • @leewangzhong, 1. it would be declaration of different class. 2. you don't need it. – klm123 Nov 09 '13 at 07:20

2 Answers2

29

Less known alternative is to make class Anon a member class of A. Inside class A you only need a line class Anon; -- no real code, no friend declaration. Note it goes within class A, almost as in Java. In the .cpp file you write all the details about Anon but you put it not in anonymous namespace but withinA::

  class A::Anon { ..... };

You can split declaration and implementation of A::Anon, as usual, just remeber always add A:: to Anon.

The class Anon is a member of A and as such gets access to all other members of A. Yet it remains unknown to clients of A and does not clutter global namespace.

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24
  • Awesome, I didn't know this trick neither, perfectly fits my current need. – wip Oct 09 '14 at 03:08
  • I'm not sure why this surprised me so much, since I now recall that it's a crucial facet of most pimpl patterns - but it's only now that I've run into a similar (but entirely non-Java-derived ;-) question that I had to properly think about the implications of this... and ***WOW***. `mind = blown;` I was using a `friend class` before now, but that just felt wrong somehow, whereas this is a much better expression of what I wanted. – underscore_d Aug 08 '16 at 19:33
  • 3
    Sadly these still have **external linkage**. Hopefully with Modules it will be possible to create completely internal classes, visible only within the module, but still being able to declare these as friends to other classes in the same module. – user362515 Jun 19 '17 at 15:14
5

As far as I can see you can not. The reasons:

  1. The “anonymous” namespace is accessible only within the file you created it in.
  2. You have to define whole AnonClass class and it's functions in one namespace, i.e. in one place in the program.
  3. Class A has to be defined before AnonClass constructor.
  4. AnonClass has to be at least declared before class A.

So you see, you can't break AnonClass definition on two parts. And you can't define it both before and after A class.

The only option - put class A into the same anonymous namespace. This code works:

namespace 
{
  class A
  {
   public:
    A():a(0){};
   private:
    int a;

    friend class AnonClass;
  };

  class AnonClass
  {
  public:
    AnonClass(A* parent);
  };

  AnonClass::AnonClass(A* parent)
  {
      parent->a = 0;
  };
}

int main() {
  A a;

  return 0;
}

I hope this helps.

klm123
  • 12,105
  • 14
  • 57
  • 95
  • I am not making sense of what you said. If you include the header into the file of the anonymous namespace, the header file can access the internal linkage names. And I definately have no clue what 2-4 is saying. – user13947194 Jul 17 '22 at 03:06