Exposing Privates

Let’s say I have

foo.h

class Foo {
 public:
  void Complicated();

 private:
  void Helper();
  int my_data_;
};

Helper is kind of complicated too -> I want to be able to test it, but it shouldn’t be a public member of Foo. I could use friend to expose Helper to test, but that’s dirty. How about this solution:

foo.h:

class Handle;

class Foo {
 public:
  Foo();
  ~Foo();

  void Complicated();

  // etc.

 private:
  /* Moved to Handle
  void Helper();
  */

  int my_data_;

  Handle* handle_; // Seems I cannot use std::unique_ptr :(
  friend class Handle;
};

foo.cc:

#include "foo.h" // existing include
#include "private.h" // New!

Foo::Foo() : handle_(nullptr) {
  new Handle(this); // Handle constructor sets this.handle_
}

Foo::~Foo() {
  delete handle_;
}

/*
void Foo::Helper() {
  my_data_++
}
becomes...
*/

void Handle::Helper() {
  foo_->my_data++;
}

// etc.

private.h:

class Foo;

class Handle {
 public:
  Handle(Foo* foo) : foo_(foo) {
    delete foo_.handle_;
    foo_.handle_ = this;
  }

  void Helper();

 private:
  Foo* foo_; // Not owned.
};

I don’t ship private.h (only foo.h), but my test can include it! I can construct Foo as before, but now, I can make a back door from test like so:

TEST(FooTest, Helper) {
  Foo foo;
  Handle* handle = new Handle(&foo);
      // Foo takes ownership ->
      // No need to worry about deleting handle.

  handle->Helper(); // Accessing "private" from test. BWAHAHAHA!
}

This is similar to pimpl in that the privates go in a separate holding class. The difference is that you can INCREMENTALLY move stuff in an existing to the holding class.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s