The King of Dirty Hacks
Sometimes in C++ you may feel the need to write a piece of code that uses private functionality of third-party classes. This could be very noticeable with Qt, where you have very little control on included classes, and asking nice Trolls to include functionality you need could take some time, and the only alternative would be duplicating half of Qt-code and modifying class names. But there’s a neat trick that was advised to me by Justin. Interested? Read along.
Why can’t you just simply gain access to all private instance and class variables and methods? Because compiler sees the private directive and restricts you. Well, it’s even very hard to get access to protected variables of an instance even if you create a subclass. But what if these nasty restricting directives weren’t there, so there would be nothing to complain about?
#define private public
Would it work? It seems so, because class data structure is arranged together, and access specifiers are not stored anywhere, and check is performed only during compile time.
How to use this technique? Plain simple, but it should always be considered only as last resort when no other solution works for you and you absolutely must gain access to that private instance variable. Recently I met a case that was nearly impossible to solve without using this dirty hack: I needed to create a QTextDocumentFragment from QTextCursor’s current selection. And guess what? It’s not possible to get hold of QTextDocumentFragment’s data structures (namely, QTextDocument of selected fragment itself, to iterate through its QTextFragments) in Qt 4.1.0! Very disappointing when you want to implement useful feature. So, here’s how I actually worked around it:
#define private public
#include <QTextDocumentFragment>
#undef private
And yes, this should be done at the very top of source file, to make sure that useful header wasn’t already #included somewhere.
(from www.gotw.ca)
Criminal #2: The Pickpocket
The Pickpocket’s hack of choice is to silently change the meaning of the class definition. For example:
// Example 2: Evil macro magic
//
define private public // illegal
include “x.h”
void Hijack( X& x )
{
x.private_ = 2; // evil laughter here
}
This man is a pickpocket. Mark him well, for his fingers are light.
The code in Example 2 is nonportable for two reasons:
a) It is illegal to #define a reserved word.
b) It violates the One Definition Rule, as above. Still, if the object’s data layout is unchanged, the hack may seem to work for a while.