Explicit callbacks or virtual methods

I’m in a bit of a quandary. I’m writing a class that does processing on a byte stream. You poke bytes in, it does stuff, it gives you bytes out. My quandary revolves around how it gives you the bytes…

The processor operates in two directions, that is, there’s an inside and an outside. It processes data traveling from inside to outside and also from outside to inside. Poking a set of bytes into the processor in one direction may or may not result in bytes being output in that direction and may or may not result in bytes being output in the other direction. My initial sketch of a design is something like:

   public:

      void Write(
         const BYTE *pData,
         size_t dataLength);

      void ReadCompleted(
         const BYTE *pData,
         size_t dataLength);

   private :

      virtual void OnWrite(
         const BYTE *pData,
         size_t dataLength) = 0;

      virtual void OnReadCompleted(
         const BYTE *pData,
         size_t dataLength) = 0;

But it could, as easilly be

   public:

      class ICallback
      {
         public :

            virtual void OnWrite(
               const BYTE *pData,
               size_t dataLength) = 0;

            virtual void OnReadCompleted(
               const BYTE *pData,
               size_t dataLength) = 0;
      };

      Processor(
         ICallback &callback)
      :   m_callback(callback) {}

      void Write(
         const BYTE *pData,
         size_t dataLength);

      void ReadCompleted(
         const BYTE *pData,
         size_t dataLength);

In the first you’d derive from the processor and implement the virtual functions; they’re be called when data was ready and you’d do stuff with it. In the second you derive from the callback and pass that to your processor and it would call you back when it had data. So which is best, and why?

I’ve had to do something similar to this a couple of times in the recent past. Unfortunately I’ve done it differently each time and, on one occasion, I seem to have taken a half and half approach (one method on the callback, one as a virtual, not quite sure why, the surrounding code may tell me if I care to look). Since we can’t change the callback for the life of the processor object and since we need to create a class which implements the methods in either instance I’m tempted to think it doesn’t actually matter. Of course we can always convert one style to another with a shim class anyway so it’s no biggie in terms of long term decisions…

I’m just curious if anyone has any views one way or the other.