Reputation: 111
I am required to provide a solution to the following problem:
A class is published as a library and made available to the world. It is designed in a way which does not use the pimpl approach. Two new data members need to be defined in this class. How can these additional data members be added to the class without breaking the ABI? The solution should be a generic approach that can be used to avoid ABI breakages for any class designed, which does not use the pimpl approach.
My first solution was to create a new class which inherits from this previous class and then adding the 2 new members there. Then source code which require these 2 new data members can make use of this newly created class. However, my solution was marked incorrect. I was told that I must repurpose an existing data member for other purposes in a similar approach to pimpl. I did not understand what this really means, as I was not provided with any interfaces of this existing class.
What alternatives are there to pimpl which allow changes to existing classes without breaking the ABI?
Upvotes: 0
Views: 357
Reputation: 119877
My guess would be as follows.
Suppose your class contains a pointer data member, say char* x
(the type is not important) that is used for thing unrelated to your planned expansion. Your professor wants you to interpret x
as a pointer to another thing:
struct expansion {
char* newX;
int newDataMember1;
double newDataMember2;
};
Now whenever you see x
in the old code, replace it with a call to a member function getX()
:
private:
char*& getX() {
return ((expansion*)x)->newX;
}
You should initialize x
in the constructor:
x = (char*)new expansion; // or
MyClass() : x((char*)new expansion)
and free it in the destructor.
Now you have your old x
as getX()
, and the new data members (write an obvious member function to access them).
Of course you should never ever do anything like that in any real code, which is why I do not discuss smart pointers, exception safety, new style casts and other things that could be remotely considered advanced or good style. Add those to taste. This is not a way to write production code, but purely an exercise to satisfy your professor.
What if you don't have a pointer member in your class? In this case you will have to break some actual C++ rules (in addition to principles of good software design, which went down the drain the moment you started even thinking about this "solution"). Repurpose some integral member instead (note, the C++ standard doesn't guarantee it will work at all, though with most implementations it's OK as long as the size of your member is at least the size of a pointer). Or repurpose more than one member that are adjacent to each other (use reinterpret_cast
or placement new
to place a pointer there). Or, if your class has a vector
of something, use data managed by the vector to store a pointer, again with a cast or placement new
hack. Everything goes... as long as you get your professor's approval of course, the C++ standard be damned.
Upvotes: 2