We have started working on a project that uses a library that we are not allowed to modify . We find ourselves with the problem that we need to change the internal state of some objects of this library but the interface of these objects does not offer methods for it:
class Clase
{
std::string dato1;
std::string dato2;
public:
void actualiza1(std::string valor) { dato1 = valor; }
};
As can be seen in the simplified example, we can change Clase::dato1
but we have no way to modify Clase::dato2
:
Clase c;
c.actualiza1("Dato 1"); // Correcto.
c.dato2 = "Dato 2"; // Error! dato2 es privado!
We have tried to change the data using a pointer, but it has not been possible either:
Clase c;
using str_pClase = std::string Clase::*;
str_pClase p2 = &Clase::dato2; // Error! dato2 es privado;
c.*p2 = "Dato 2";
As a last resort we have copied the drafting of the library objects but with the public members, when we need to change the internal state of the object we use the new
placement state:
class Clase
{
std::string dato1;
std::string dato2;
public:
void actualiza1(std::string valor) { dato1 = valor; }
};
struct Estructura
{
std::string dato1;
std::string dato2;
};
Clase c;
c.actualiza1("Dato 1"); // Correcto.
Estructura *e = new(&c) Estructura;
e->dato2 = "Dato 2"; // Correcto! c.dato2 ahora es 200;
Although this seems to work, it causes other bugs as when building an object on top of an existing one, the sub-object's constructors are called and change (initialize) values of the original object that we didn't want to be modified.
Is it possible to somehow bypass the data access restriction?
Based on this SOen question
No. What you're trying to do is dangerous and against C++ standards.
Well, C++ ignores access restrictions in a specific context: The explicit instantiation of a template. This means that by explicitly instantiating a template we can access private and protected object data; the most practical would be to capture a pointer to the internal data. But it is not easy.
If we have an object that nests a member pointer:
We can use it as a " backdoor " key to an object:
To open this backdoor with our key, we need a template that we can explicitly instantiate with explicit parameters:
The above witchcraft is needed to initialize the backdoor key once (
static
) per template instance, so with your itemClase
, we'll need to open two backdoors:In the context of explicit template instantiation, access permissions are not checked, so we can access
Clase::dato1
yClase::dato2
like so:The syntax is quite cumbersome, so it would be appropriate to use a template helper function:
In case you want to call private methods, you can also declare a helper template function:
With these helper functions, backdoor access to private data would look like this:
You can see the code working on Wandbox .