A Patient is a list of Studies
A Study is a list of Series
A Series is a list of Images
So a so a series is defined as:
class series : std::list<image>
Now I'd like to implement this thing using template classes...
so:
template <tipe, subtipe>
class tipe : std::list<subtipe>
{
private:
std::string id;
public:
std::string getId();
void add(subtipe);
void remove(id);
subtipe get(id);
};
So this is the basic template...
the ID is used to locate your object in the list...
There is of course a few issues I have with this...
1) I want to be able to add an study, series or image to a patient
2) I want to be able to add a series, or image to a study.
This template only allows me to add an image to a series.
I also want to be able to remove a image from a series..
When the series is empty then the series should be removed from the study.
When the study is empty then the study should be removed from the patient.
As is was able to remove add an image to the patient so should I be able to remove an image from a patient and remove a series from a patient etc etc.
So my problem at this point is that I obviously can't I do this with the above templated class. So how can I expand this template class without writing a class for each layer of the hierarchy?
There is no need for derivation. The standard classes were not meant to be derived from anyway.
Now I'd like to implement this thing using template classes...
so:
Please post real code. The code you posted is not valid, so it is hard to understand what you really want to do.
the ID is used to locate your object in the list...
Then maybe you should have used std::map if you associate an ID with an object.
1) I want to be able to add an study, series or image to a patient
Work from the top-level down, not from the bottom-level up. You are worried about implementation details, but from what you're describing, the first thing you should have written was this:
class Study
{
};
class Series
{
};
class Image
{
};
class Patient
{
public:
void AddStudy(const Study& theStudy)
{
// add study to Studies container
}
void AddSeries(const Series& theSeries)
{
// add series to Series container
}
Then depending on the container you choose for each type, you just implement the function to add the value to the container of values. I don't see why it needs to be any more complex than this.
Regards,
Paul McKenzie
exterminator
March 29th, 2007, 11:54 PM
A Patient is a list of Studies
A Study is a list of Series
A Series is a list of ImagesWhat you call as "... is a list of ..." looks more like "... has a list of ... ". So, the relationship is not meant for public inheritance and of course, you are not doing so. I see that you have used private inheritance - not a bad choice but you should remember that when you express the relationship in words. That confused Paul McKenzie.
Standard containers are not meant to be derived from - the concept eludes me sometimes. That is suggested just because the destructor isn't virtual and that the derived object can be destroyed using the base pointer - which leads to undefined behaviour. But I am of the mind that if the destructor isn't virtual and since destructor is part of the public interface of the container class - one can easily deduce that this would lead to undefined behaviour. Which means that the user of my class should not try to use my derived object using a base pointer because my base class (the standard containers) don't have any virtual functions to exploit polymorphism. So, there is no sensible way one would want to use this type hierarchy in a polymorphic way - which keeps it safe. If one does so, he is at fault and should get penalized. To conclude, I am of the mind that - if one is sure of what he is doing there is no explicit reason as to not deriving from the standard containers.So my problem at this point is that I obviously can't I do this with the above templated class. So how can I expand this template class without writing a class for each layer of the hierarchy?I did not understand what you said your problem was. Can you post the interfaces (not the implementations, just the class definitions) that you have as of now and point out the problem from that?
JVene
March 30th, 2007, 11:08 AM
To my mind, your problem is solved easily.
First, you have the need for a structure that represents each of these notions. They are so different, I can't imagine that a collection of images could be based on the same class as, say, a collection of studies.
So, you have a patient class which has a container for a collection of studies.
The study class has a container for a collection of series.
The series class has a container for a collection of images.
When you add type image, you MUST specify the series it belongs in, don't you? - that problem solved....
In order to specify the series, you have to know which study that's in, right?
That seems quite clean to me.
Have a new image for a new series in a new study on an existing patient? Everything's new except the patient....
If your purpose was to attempt a single class that can do this, such that you don't have a container in these objects - that is, you don't want to put a container of images in a series, then I ask why?
If you created a template class, you could create a template that has a container to a different type. With this you could make an int that also contains a series of doubles, a string that contains a series of vectors, a study that contains a collection of images (yes, I know - you mean to create a study that contains a collection of series).....
That's part of my point. Your structure seems fairly simple and 'cast in stone' - you don't need to mix/match these types. If you did, perhaps such a class is ok.
Next, it would seem appropriate to me that a study needs to be aware of and manipulate it's collection of series, and likewise you may need to access the collection of images in a series - which would all have to be in external functions to these object. That is, if a generic template container node, like that proposed here, is used - how could the series get to IT's images? It couldn't without accessing the node. If the container of images is a member OF series - it's just a member, no mystery about access.....
Does this make sense, or did I misunderstand the question?
JustSomeGuy
March 30th, 2007, 01:00 PM
I think I finally understand why one should not derive from standard containers.
I guess I was really hoping for too much for a single template to handle each level of the hierarchy....
The thing is that this hierarchy can grow ....
like a database is a list of Patients...
JVene
March 30th, 2007, 02:33 PM
You could create a template class to do this, and there are perhaps reasons for wanting to. I still think you should follow McKenzie's construction, perhaps placing a list<study> as a member of patient, a list<series> as a member of study, and a list<image> as a member of series.
To create a database, which has a member list<patient> is a trivial modification to this structure.
However, this is also possible, with side effects (please read as psuedo code, not tested or known to be correct):
template<class parent, class child> class Hnode : public PNode<parent>
{
private:
list<PNode<child> *> childlist; // should consider some kind of smart pointer here
public:
};
Fleshed out, this Hnode has a parent data member, and a list of children of a different type (a type you've related). Thus, a
Hnode<database, patient> dbase;
woudl accept patients made with
new HNode<patient, study>;
which would accept study objects, each created as
new HNode<study, series>;
which would themselves accept a series object, created as
new HNode<series, image>;
each created as a 'final' node type:
new PNode<image>
The problem with this construction is that a patient doesn't 'know' it's studies - it has to ask the HNode for that.
The series doesn't know it's images, it must ask the HNode for that.
However, any generic algorithm that understood the PNode/HNode relationship could, through virtual functions, walk through the hierarchy without understand the types it contains.
This would be useful for a custom tree control, for example - but for other algorithmic construction, complicates the use of the various objects as they are used to represent a patient, or a study, etc....(since they can't get to their 'kids' without help).
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.