Rename MFC CArchive Serialized class - c++

I'm using MFC's CArhive class to save off a project file for my app. One of the class names is wildly inaccurate and I'd like to change it, but simply changing the name everywhere renders previous archive files useless with an archive error. Is there a way to change the name of the archived class without rendering all previously saved files useless?
That is of course without using a typedef to access the existing class with a new name or keeping around a version of the class with the old name to read archived files and copying the read in objects to the same class with a new name.

The crucial point is that when you use DECLARE_SERIAL and IMPLEMENT_SERIAL, a CRuntimeClass member is added to your class containing the name in its m_lpszClassName field.
This CRuntimeClass object is also added to a list maintained by the framework that is searched when classes are dynamically created.
You need to make sure that the CRuntimeClass object contains the old name of your class in m_lpszClassName.
The two options you have are:
Override the construction of the
CRuntimeClass object to set the name
Change the class name stored in its
m_lpszClassName field after it has
been created
Overriding the construction of the CRuntimeClass object
To do this, you will need to make your own versions of DECLARE_DYMAMIC, DECLARE_DYNCREATE, DECLARE_SERIAL, IMPLEMENT_DYMAMIC, IMPLEMENT_DYNCREATE, and IMPLEMENT_SERIAL.
You can just copy and rename the existing implementations.
In your version of IMPLEMENT_DYNAMIC, you need to change the code that constructs the CRuntimeClass so that it is initialised with the old class's name.
Changing the class name stored in the m_lpszClassName field after the CRuntimeClass object has been created
As the CRuntimeClass is created by a static initializer, I don't think that you can do this from within your class.
I think that the best place to do it is in your application's InitInstance.
Add a static char* variable to your application's class containing the old class name.
Then, in InitInstance, set the m_lpszClassName field in your class's CRuntimeClass.
The first method has the advantage of
keeping changes within the class
itself.
The second makes the application
aware of the class in a way that it
possibly shouldn't be.
Either way, the first thing to do is to completely familiarise yourself with the way dynamic creation and serialization work.

There is a 3rd option which I took. I originally named one of my serializable classes CEvent which didn't seem to be a problem on VC6.0; but on VS2010 there is a MFC built-in class called CEvent so I had to change it.
So, I fixed it by modifying old format files before calling COleServerDoc::OnOpenDocument
I simply, open, read to memory, find and replace CEvent with any other 6 character (has to be same size) class name, write and save as new filename, then open and read new file, no problem.
I'm changing file extension for the new version anyway, so it all works out.

Related

Dynamic Module Classes in C++

I created, in a nutshell, a txt file converter.(basically converts text files removing comments etc into other text files)
I have created varius methods of converting the file(e.x. removing only the "#" symbols etc). In the future I would like to add other methods too but without touching the initial code. I want to add another class file in a subfolder and recompile the code. Then the new conversion method would appear in my program.
How I do that?
Basically you use virtual member functions in a class, and/or template parameters, as customization points.
For run-time polymorphism (virtual member functions) this is called the open/closed principle, after Betrand Meyer:
” A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients.
For your particular case it would be natural to represent a “conversion method” as an object that you pass to a general text file converter functor object, which then uses it internally. Alternatively the “conversion method” can be a virtual function on the latter. This way of providing a procedure with customization points is called the template method pattern.
Note: the word “template” in “template method pattern” does not refer to C++ templates, but rather to the notion of the customizable procedure as a template for each concrete adaption.

How do I register global variables independently in a single global array

I'm writing this, well, call it a library I guess. It offers a set of global variables of type MyType. Now, I want to write the source of each of these MyType's in its own .cpp and .h files, unaware of all the rest, without needing some central header file saying MyType* offerings = { &global1, &global2, /*... */ }.
Now, had these been different classes I want to be able to instantiate, I would want to use a factory pattern; but here they're all of the same type, and I don't need to instantiate anything. I would think each variable needs to be 'registered' into a global array (or unordered set) from somewhere in its sources.
So, what's the idiomatic way to do this?
You could take a look at the Registry Pattern and create a manager for your filesystem or folder that will manage these objects.
The Registry could have everything related to Filesystem Handling so you insert your object names and properties in a model in one config file or database. The registry could look up that and instantiate your objects on runtime.
Now you would need a mechanism to communicate this objects to the rest of the system. But if your objects are not going to change then just a registry with compile time objects would do.
The Registry is a pattern to handle global objects in a similar fashion to the singleton.

Should I prefer a const function?

Assume I want to implement class A which must load its "configuration" from a file. And let's assume the "configuration" is a simple map<string, string>.
I can implement the A::LoadConfiguration in two different ways:
void A::LoadConfiguration(string filename)
map<string, string> A::LoadConfiguration(string filename) const
Should I prefer either of the two implementations, and why?
If you prefer the second version when the user wants to get info on a file they will base all their algorithms on the map. If you do the second version, meaning the implementation may be a map, but doesn't have to be, they can base their code around an API which does not have to change even if the internal implementation does.
Consider the situation where later you realize it is far more efficient to use an std array, for whatever reason, now every program using this code has to change many of it's algorithms. Using the first version the change to array can be handled internally and reflect no changes on the outside.
Now if you are planning to make multiple instances of the class you will definitely want to make it a static method because you don't want the file to load every time you call the constructor (especially if the file will not change).
Completely ignoring your suggestions, but this is probably how I would do it (not knowing all your constraints, so ignore me if it does not fit):
class A
{
public:
static A fromConfiguration( string fileName );
/* ... */
}
In most cases, the "configuration" of a class should be set at object creation, so forcing the user to provide it on construction is a good thing (instead of having to remember to do do the loading later).
namespace NeatStuff
{
map<string,string> loadSimpleConfiguration( string fileName );
}
If the configuration file format is really simple (and not specific to your class) you can move the actual loading out of the class.
Assuming other classes use the configuration later, I prefer option 1, and an additional GetConfigurationParameter public const method that gets the config value for a particular key. That lets me make other classes which can just ask for some parameter by name without ever caring that it's implemented as a map.
Another reason why I prefer option 1 is that loading a configuration should be distinct from returning it. If I see a name like LoadConfiguration, I assume that it loads the config from somewhere and sets the parameters in the class. I do not assume it returns some description of the configuration, which I'd instead expect from a method like GetConfiguration - but opinions on this will vary for different people of course.

Suggestion on C++ object serialization techniques

I'm creating a C++ object serialization library. This is more towards self-learning and enhancements & I don't want to use off-the-shelf library like boost or google protocol buf.
Please share your experience or comments on good ways to go about it (like creating some encoding with tag-value etc).
I would like to start by supporting PODs followed by support to non-linear DSs.
Thanks
PS: HNY2012
If you need serialization for inter process communication, then I suggest to use some interface language (IDL or ASN.1) for defining interfaces.
So it will be easier to make support for other languages (than C++) too. And also, it will be easier to implement code/stub generator.
I have been working on something similar for the last few months. I couldn't use Boost because the task was to serialize a bunch of existing classes (huge existing codebase) and it was inappropriate to have the classes inherit from the interface which had the serialize() virtual function (we did not want multiple inheritance).
The approach taken had the following salient features:
Create a helper class for each existing class, designated with the task of serializing that particular class, and make the helper class a friend of the class being serialized. This avoids introduction of inheritance in the class being serialized, and also allows the helper class access to private variables.
Have each of the helper classes (let's call them 'serializers') register themselves into a global map. Each serializer class implements a clone() virtual function ('prototype' pattern), which allows one to retrieve a pointer to a serializer, given the name of the class, from this map. The name is obtained by using compiler-specific RTTI information. The registration into the global map is taken care of by instantiating static pointers and 'new'ing them, since static variables get created before the program starts.
A special stream object was created (derived from std::fstream), that contained template functions to serialize non-pointer, pointer, and STL data types. The stream object could only be opened in read-only or write-only modes (by design), so the same serialize() function could be used to either read from the file or write into the file, depending on the mode in which the stream was opened. Thus, there is no chance of any mismatch in the order of reading versus writing of the class members.
For every object being saved or restored, a unique tag (integer) was created based on the address of the variable and stored in a map. If the same address occurred again, only the tag was saved, not the deep-copied object itself. Thus, each object was deep copied only once into the file.
A page on the web captures some of these ideas shared above: http://www.cs.sjsu.edu/~pearce/modules/lectures/cpp/Serialization.htm. Hope that helps.
I wrote an article some years ago. Code and tools can be obsolete, but concepts can remain the same.
May be this can help you.

What is the best way to auto-generate values for features when an EObject is created?

I have some attributes in my EClasses I would like to initialize to a computed value when an instance is created. I'm wondering what the recommended way to do this using the framework is.
In one case I'd like to initialize the id attribute to a UUID. In this case I'd like the UUID value to be assigned when the object is first created and then remain the same for the life of the object.
In another case I'd like to generate a short id that only needs to be unique within the model instance.
I'm new to EMF and would greatly appreciate any guidance.
In both cases, I usually make the attributes suppress Setter and initialize the them in the default constructor.
the UUID is generated via EcoreUtils.generateUUID()
the class unique id is generated from a class static nextID
The attributes are not made unchangeable as we must (normally) be able to load a XML file and these must take precedence over the ones set in the constructors.
The class unique id, is slightly more difficult to handle as we must also initialize nextID to a good value when the application starts.
Consider the sequence where we create a number of objects first and then load an old file: how do we ensure there are no duplicates between the objects? One possible method is to divide the id into two parts: a timestamp and a sequence number. Assuming we cannot restart the application within the resolution of the timestamp (usually one second) this works quites all right.
This solution still assumes we never need to load two or more old files as these may conflict if created at the same time in different application instances....
All-in-all, I normally stick with UUIDs as this method avoids all of the above problems :-)