SIGPIPE 13

Accessing Protected Data

May 6th, 2010

Whenever I see something that intrigues me, my mind makes a note of it and then subconsciously works toward finding a use-case for my newfound knowledge.

An example is that I recently learned how protected member data (C++) is actually not safe from outside pryers (even in clean code that does not use typecasts).

Given a base class:

class Base
{
protected:
    int foo () { return 42; }
};

We can create a new derived class which changes the visibility of the foo member function to public like this:

class Derived : Base
{
public:
    using Base::foo;
};

This is not new, perhaps with the exception of the using keyword. This is normally used with private inheritance where one selectively expose member functions from the private base class.

The trick is that via Derived we can now obtain a pointer to the previously protected member function (foo) outside of the class:

int(Base::*fn)() = &Derived::foo;

The type syntax for (member) functions is arcane, but notice that even though we go through Derived to get the pointer, the actual type of the pointer has it as a member function of Base since Derived doesn’t redeclare the function, it simply re-expose it (via using).

So fn can be used directly with Base objects via the syntax for calling member functions given a pointer to them (the .* and ->* operators):

Base obj;
printf("%d\n", (obj.*fn)());

Or without using a variable to hold the member function pointer:

Base obj;
printf("%d\n", (obj.*&Derived::foo)());

Eureka!

Unit Tests

Generally I write unit tests only for public API, my reasons for this are many:

You may wonder what public API exists in something like a desktop application. What I do is write a module/library/framework whenever I have related functionality. For example TextMate 2 is presently built from 35 libraries. Each library expose types or functions related to a particular thing and that is the public API I write the tests for.

But back to why I need to access protected member data when I only test the public API. The reason for this is that some public types have private callbacks normally called by the OS, for example when a file changes on disk, the type for a document will have a private (now protected) callback invoked due to use of kqueue. Exactly when the callback is invoked is undefined which isn’t ideal for a unit test, so I have to cheat and call it myself, and that is why I need to access protected member data.

Sure, I could just make the callback a public function since there are less cases than I can count on one hand, but as indicated in the intro, my mind works overtime to apply the knowledge I accumulate ;)

Update: Corrected my use of ‘unit tests’ as I am writing ‘high-level tests’.

[by Allan Odgaard]


One Response to “Accessing Protected Data”

  1. Brendan Miller Says:
    May 19th, 2010 at 23:30

    Heh, one of two possible uses for pointers to members.

    I'm not a big fan of protected. If you have an object, members are either for internal use or not. If you make things protected, than you are really saying "this member is public, but I wan't to force you to write a whole class before you can call it."

    Then there's languages like Python that don't even bother with access control, and I can't say I miss it.


Leave a Reply