Anonymous Classes in Java and C++


An anonymous class is a shorthand way of creating a class without an explicit name. Java primarily uses anonymous classes to make it easier for the developer to connect objects together, since they can be declared where they are needed. Java anonymous classes differ from those in C++ in that the scoping rules — what the object has access to — are not as restrictive. In C++, an object of an anonymous class (a.k.a. nested class) has access to its containing object's members only if it is declared within the definition of that object's class. If an anonymous class is declared in the body of a method, the instantiated object is treated as just another object — it does not have access to members of the method's containing class.

On the other hand, Java anonymous classes do have access to the containing object's members, even if the class is declared in the body of a method. For example, the following Java class constructor anonymously subclasses the SwitchBoardAdapter to override the deliver method and call the containing class MyClass's busy method.

MyClass()
{
  SwitchBoard.subscribeTo("busy",
    // anonymous subclass
    new SwitchBoardAdapter() {
      public void deliver(String msg) { busy(msg); }
    }
  );

  public void busy(String msg) { /* do something */  }
}

The same thing can be accomplished in a C++ method by using an anonymous subclass, but only if the anonymous subclass can store a reference to the containing object. The anonymous subclass will require an additional method to store that reference. After obtaining a reference to the containing object, the anonymous subclass can reference any of its public members, or more restricted ones if it is declared as a friend. For example, the following C++ constructor code anonymously subclasses the SwitchBoardListener to override the virtual deliver method, resulting in the same functionality as the Java anonymous subclass above.

void MyClass::MyClass()
{
  // anonymous subclass
  class SwitchBoardListener {
    MyClass* _target;
  public:
    void setTarget(MyClass* target) { _target = target;   }
    void deliver(const char* msg)   { _target->busy(msg); }
  } adapter;
  adapter.setTarget(this); // requires two steps to set the target
  SwitchBoard.subscribeTo("busy", adapter);  // must copy
}

void MyClass::busy(const char* msg) { /* do something */  }

C++ does not use this technique very often for several reasons. First, this technique is error prone. (The object is only in scope where it is declared, so the entire class definition must be copied everywhere it is used.) Second, it is awkward. (A reference to the container object must be set.) Finally, better alternatives exist. Some of the more clever alternatives that have been developed for windowing systems include message mapping (using events instead of OO methodologies), multiple inheritance in conjunction with event handling, and C function callbacks. Outside of a framework that provides this functionality, the next best thing is a template. A template can be used instead of an anonymous subclass to generalize the delivery process, reduce the risk of misuse, and provide a reusable component. The following template could be used in place of the C++ anonymous subclass in all instances where a SwitchBoardListener is needed.

template <class T> class SwitchBoardAdapter
{
private:
  T* _target;

public:
  SwitchBoardAdapter(T* target) : _target(target)    { }
  void deliver(const char* msg)  { _target->busy(msg); }
};

void MyClass::MyClass()
{
  SwitchBoard.subscribeTo(
    "busy", new SwitchBoardAdapter<MyClass>(this)
  );
}