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.
Related
I ended up in a situation lined out below.
I have one library that is pure CPP without external libraries, and another project that is an SDK to interface with an external library.
"I" in front of the name indicates an abstract class. Arrows indicate inheritance.
I have IDevice which contains HandleInput(data) as a callback, and StartDevice().
Then I have a more specific type of device: ISmartwatch (containing StartTimer), and from that inherits a more specific version SmartwatchV1, which implements HandleInput(data) according to its needs.
That all seemed great until I came to the external SDK part, where the library expects me to use inheritance to interface with it to override some functions. So, I have to inherit from the external library, and from my own CPP library, to override the functions I need. Most of these library overrides suit any device (IExternalLibDevice), but a few are specific to the exact Stopwatch version (ExternallSmartWatchV1).
Then for polymorphism in my SDK, I would like to call and override functions both provided by the library and my own device example: libDevice.StartDevice() and use library calls within this optionally overriden StartDevice. Or stopWatch.StartTimer(), stopwatchV1.libraryOverride().
The object which I need to create is the green one, however, the white SmartWatchV1 is also an object to instantiate in applications without the library. (And obviously I keep in mind any future alternative devices or stopwatch versions.)
I think if I drop any inheritance arrow, I would either lose out on polymorphism (so SDK code will only work for a very specific smartwatch version), or I cannot override functions I need anymore. Composition would be nice, but won't work for overriding functions, or is there an option I don't know about?
And so, I ended up here. I am encountering quite some annoying errors implementing this, since double diamond is usually solved with virtual inheritance (nice page about double diamond: https://isocpp.org/wiki/faq/multiple-inheritance#mi-diamond). However, when applied here (see the v's that indicate "virtual" in the image), I have one inheritance that should both be virtual and not be virtual. Additionally, virtual inheritance makes constructors really annoying in my generic CPP library. Even without virtual (which as far as I'm aware would cause some duplication of classes in memory and a lot of ambiguity to solve), I have some constructor errors ("no suitable default constructor" for a class that must not have a default constructor, etc) issues.
I have been battling to solve this for a long time, and I hope someone more experienced can make a suggestion that provides a better solution for my code structure or issue.
In the end, I solved it by using composition:
Add an IDevice pointer to IExternalLibDevice that is set in the constructor.
In IExternalLibSmartwatch: add an ISmartwatch pointer to the constructor and pass it to its parent constructor. Also, add a function that retrieves the IDevice pointer as an ISmartwatch.
In ExternalSmartwatchV1: also add a SmartwatchV1 to the constructor and pass it to its parent constructor, and create a function that retrieves the IDevice pointer as a SmartwatchV1.
The IDevice pointer holds the reference to the cppLibDevice, and can now be cast to any of the subclasses it belongs to. Downside: I cannot override the cpp lib classes, but it was not a hard requirement for my code, since I created alternative functions in the ExternalLib classes that can optionally call the cppLibDevice functions, or completely replace them.
I'm fairly new to c++ templates.
I have a class whose constructor takes two arguments. It's a class that keeps a list of data -- it's actually a list of moves in a chess program.
I need to keep my original class as it's used in other places, but I now need to pass extra arguments to the class, and in doing so have a few extra private data members and specialize only one of the private methods -- everything else will stay the same. I don't think a derived class helps me here, as they aren't going to be similar objects, and also the private methods are called by the constructor and it will call the virtual method of the base class -- not the derived method.
So I guess templates are going to be my answer. Just looking for any hints about how might proceed.
Thanks in advance
Your guess is wrong. Templates are no more the answer for your problem than inheritance is.
As jtbandes said in comment below your question, use composition.
Create another class that contains an instance of your existing class as a member. Forward or delegate operations to that contained object as needed (i.e. a member function in your new class calls member functions of the contained object). Add other members as needed, and operations to work with them.
Write your new code to interact with the new class. When your new code needs to interact with your old code, pass the contained object (or a reference or a pointer to it) as needed.
You might choose to implement the container as a template, but that is an implementation choice, and depends on how you wish to reuse your container.
Templates are used when you want to pass at compile time parameter like values,typenames, or classes. Templates are used when you want to use exactly the same class with the same methods, but applying it to different parameters. The case you described is not this I think.
If they aren't goign to be similar objects you may want to create a specialized class (or collections of function) to use from the various other classes.
Moreover you can think of creating a base class and extending it as needed. Using a virtual private method should allow you to select the method implementation of the object at runtime instead of the method of the base class.
We may help you more if you specify what does they need to share, what does your classes have in common?
The bare bones of my present code looks like this:
class move_list{
public:
move_list(const position& pos, unsigned char ply):pos_(pos),ply_(ply){
//Calculates moves and calls add_moves(ply,target_bitboard,flags) for each move
}
//Some access functions etc...
private:
//private variables
void add_moves(char,Bitboard,movflags);
};
Add_moves places the moves on a vector in no particular order as they are generated. My new class however, is exactly the same except it requires extra data:
move_list(const position& pos, unsigned char ply,trans_table& TT,killers& kill,history& hist):pos_(pos),ply_(ply),TT_(TT),kill_(kill),hist_(hist) {
and the function add_moves needs to be changed to use the extra data to place the moves in order as it receives them. Everything else is the same. I guess I could just write an extra method to sort the list after they have all been generated, but from previous experience, sorting the list as it receives it has been quicker.
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.
We have an internally used type of file here that is basically a table where columns can have different types. There is also a header with IDs identifying which column is which type. Users typically do not generate table layouts all the time, there is rather a limited set of table layouts (say 10 or so, but more to come in the future).
My question is: What is the best approach to model this file in C++?
I can think of the following possibilities:
Create a templated file class where the template parameter is a struct containing the types of the columns.
In a different, static template class, put the header IDs as a static member and provide a function for endianness-safe reading (via explicit template specialisation).
Disadvantage: Need to create struct and static partner class for each file. Will fail at link time if static template class has no specialisation for this type. Is perhaps a misuse of templates.
Create an abstract data class, derive explicit overrides for each type that can be in a column and dynamically cast the pointers-to-base-class that I get from the file back to the right type (which I can find out via the header).
Disadvantage: Dynamic cast on every read.
Create a templated file class as above. Require from the template that it has methods which read and write a file header and provide endianness-safe reading.
Disadvantage: Need to create class with these methods for each file type instead of using plain structs as in 1. Require explicit template specialisations for built-in types.
Any other suggestions?
Since files are read-up at run-time, compile time solutions aren't real "solution".
This is a typical case for a "hierarchy of polymorphic classes" sharing a common root, destined to a collection of unique_ptr or shared_ptr to dynamic_cast from.
basically, you guess the type from the data format, and push_back a x_ptr<BaseClass>(new ActualClass).
BaseClass can hold a way to allow you to recognize which ActualClass you're dealing with, but that's noting more what dynamic_cast does. Just let BaseClass empty, with just a virtual destructor.
On the file, every record must start with a sort of "type_id" the actually tells you what is the actual type the following data represent.
Options:
Use self-descriptive data types ("type-size-value" triples), and perform cast per type.
Use XML structures (variation of the above, basically)
Use relative database (SQLite embedded in your code, for example, or anything else)
As I understand, the pimpl idiom is exists only because C++ forces you to place all the private class members in the header. If the header were to contain only the public interface, theoretically, any change in class implementation would not have necessitated a recompile for the rest of the program.
What I want to know is why C++ is not designed to allow such a convenience. Why does it demand at all for the private parts of a class to be openly displayed in the header (no pun intended)?
This has to do with the size of the object. The h file is used, among other things, to determine the size of the object. If the private members are not given in it, then you would not know how large an object to new.
You can simulate, however, your desired behavior by the following:
class MyClass
{
public:
// public stuff
private:
#include "MyClassPrivate.h"
};
This does not enforce the behavior, but it gets the private stuff out of the .h file.
On the down side, this adds another file to maintain.
Also, in visual studio, the intellisense does not work for the private members - this could be a plus or a minus.
I think there is a confusion here. The problem is not about headers. Headers don't do anything (they are just ways to include common bits of source text among several source-code files).
The problem, as much as there is one, is that class declarations in C++ have to define everything, public and private, that an instance needs to have in order to work. (The same is true of Java, but the way reference to externally-compiled classes works makes the use of anything like shared headers unnecessary.)
It is in the nature of common Object-Oriented Technologies (not just the C++ one) that someone needs to know the concrete class that is used and how to use its constructor to deliver an implementation, even if you are using only the public parts. The device in (3, below) hides it. The practice in (1, below) separates the concerns, whether you do (3) or not.
Use abstract classes that define only the public parts, mainly methods, and let the implementation class inherit from that abstract class. So, using the usual convention for headers, there is an abstract.hpp that is shared around. There is also an implementation.hpp that declares the inherited class and that is only passed around to the modules that implement methods of the implementation. The implementation.hpp file will #include "abstract.hpp" for use in the class declaration it makes, so that there is a single maintenance point for the declaration of the abstracted interface.
Now, if you want to enforce hiding of the implementation class declaration, you need to have some way of requesting construction of a concrete instance without possessing the specific, complete class declaration: you can't use new and you can't use local instances. (You can delete though.) Introduction of helper functions (including methods on other classes that deliver references to class instances) is the substitute.
Along with or as part of the header file that is used as the shared definition for the abstract class/interface, include function signatures for external helper functions. These function should be implemented in modules that are part of the specific class implementations (so they see the full class declaration and can exercise the constructor). The signature of the helper function is probably much like that of the constructor, but it returns an instance reference as a result (This constructor proxy can return a NULL pointer and it can even throw exceptions if you like that sort of thing). The helper function constructs a particular implementation instance and returns it cast as a reference to an instance of the abstract class.
Mission accomplished.
Oh, and recompilation and relinking should work the way you want, avoiding recompilation of calling modules when only the implementation changes (since the calling module no longer does any storage allocations for the implementations).
You're all ignoring the point of the question -
Why must the developer type out the PIMPL code?
For me, the best answer I can come up with is that we don't have a good way to express C++ code that allows you to operate on it. For instance, compile-time (or pre-processor, or whatever) reflection or a code DOM.
C++ badly needs one or both of these to be available to a developer to do meta-programming.
Then you could write something like this in your public MyClass.h:
#pragma pimpl(MyClass_private.hpp)
And then write your own, really quite trivial wrapper generator.
Someone will have a much more verbose answer than I, but the quick response is two-fold: the compiler needs to know all the members of a struct to determine the storage space requirements, and the compiler needs to know the ordering of those members to generate offsets in a deterministic way.
The language is already fairly complicated; I think a mechanism to split the definitions of structured data across the code would be a bit of a calamity.
Typically, I've always seen policy classes used to define implementation behavior in a Pimpl-manner. I think there are some added benefits of using a policy pattern -- easier to interchange implementations, can easily combine multiple partial implementations into a single unit which allow you to break up the implementation code into functional, reusable units, etc.
May be because the size of the class is required when passing its instance by values, aggregating it in other classes, etc ?
If C++ did not support value semantics, it would have been fine, but it does.
Yes, but...
You need to read Stroustrup's "Design and Evolution of C++" book. It would have inhibited the uptake of C++.