Accessing Protected Data
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:
Unittests for me is to a big degree a way of “documenting” and ensuring simplicity of my APIs.- There are too many private functions, writing unit tests for these is a waste of time as they are both simple and using assertions.
- Private functions are those which change regularly, and I don’t want to be discouraged from refactoring because of the double work in also updating unit tests.
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’.